0

基本的にハートビートであるクラスを作成しました。クライアントは x 秒ごとにサーバーにメッセージを送信します。

恥知らずに盗まれた コードを送る

  private void SendUdpPacket() {
        byte[] data = new byte[1024];
        Socket udpClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        data = Encoding.ASCII.GetBytes("lubdub");
        udpClientSocket.SendTo(data, 0, data.Length, SocketFlags.None, ipep);
    }

恥知らずに盗まれたコードを受け取る

void ReceiveData(IAsyncResult iar) {
        byte[] buffer = new byte[1024];
        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
        EndPoint tempRemoteEP = (EndPoint)sender;
        Socket remote = (Socket)iar.AsyncState;
        int recv = remote.EndReceiveFrom(iar, ref tempRemoteEP);
        string stringData = Encoding.ASCII.GetString(buffer, 0, recv);
        Console.WriteLine(stringData);
        lastUpdate = DateTime.Now.ToUniversalTime();
        if (!this.IsDisposed) {
            udpServerSocket.BeginReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref ep, new AsyncCallback(ReceiveData), udpServerSocket);
        }

これは、内部タイマーによって監視されます

private void clTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
        try {
            SendUdpPacket();
            connected = true;
        } catch {
            connected = false;
        }
    }
    private void srTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
        // Calculate the Timespan since the Last Update from the Client.
        timeSinceLastHeartbeat = DateTime.Now.ToUniversalTime() - lastUpdate;

        if (timeSinceLastHeartbeat > TimeSpan.FromMilliseconds(Timer.Interval))
            connected = false;
        else
            connected = true;
    }

メッセージが成功した場合、ソケットが接続されます。これは public ブール値で示されますconnected

したがって、私のアプリケーションでは、次のようにタイマーを実行します。

        private void ServerCheck() {
        if (heartin.connected) {
            GKstat = true;
            GKStatus.Text = "GateKeeper Status: Connected";
        } else {
            GKstat = false;
            GKStatus.Text = "GateKeeper Status: Disconnected";
        }
    }

ただし、クライアントまたはサーバーのタイマーが接続されているかどうかを常に確認する必要があるため、これは理想的ではありませんHeart

これを一連のイベントに変換することが有益かどうか疑問に思っていましたOnConnectionLost.OnConnected

私はいろいろなページを見回して読んでいましたが、それらは私をさらに混乱させるだけでした.

これは私がこれまでに持っているものです

    public delegate void OnConnectionLost(Heart sender, EventArgs e);
    public delegate void OnConnected(object sender, EventArgs e);

    public event OnConnectionLost ConnectionLost;

私の質問は、これは有益でしょうか?もしそうなら、接続状態が変化したときにのみ発生するような方法でイベントを作成するにはどうすればよいですか?

4

1 に答える 1

1

これは、ブール値が悪となるシナリオの 1 つです。次のenumようなものを作成することを強くお勧めします。

public enum ConnectionState
{
    Disconnected = 0,
    Disconnecting = 1,
    Connecting = 2,
    Connected = 3,
    // etc.
}

これを などのプロパティに使用できますConnectionState。さらに、EventHandler<T>独自のカスタム デリゲート タイプの代わりに標準デリゲートを使用するのが一般的です。例えば:

public sealed class ConnectionStateEventArgs : EventArgs
{
    public ConnectionState ConnectionState { get; private set; }
    public ConnectionStateEventArgs(ConnectionState connectionState)
    {
        ConnectionState = connectionState;
    }
}
public event EventHandler<ConnectionStateEventArgs> ConnectionStateChanged;

これにより、現在の単純な「オン/オフ」を超えて接続状態を拡張できます。ConnectionStateプロパティをイベントと組み合わせることは、ConnectionStateChangedさまざまな API で見られる一般的な方法です。

接続状態が実際ConnectionStateに変化したときにのみ起動するには、プロパティに本体を追加するだけです。

private ConnectionState _connectionState;
public ConnectionState ConnectionState
{
    get { return _connectionState; }
    set
    {
        if (value != _connectionState)
        {
            _connectionState = value;
            var tmp = ConnectionStateChanged;
            if (tmp != null)
                tmp (this, new ConnectionStateEventArgs(value));
        }
    }
}

その後、プロパティに別の値を割り当てるだけで、イベントが発生します。

于 2015-11-17T10:12:51.393 に答える