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;
    }

如果消息成功,则套接字已连接,这通过公共布尔值显示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

这是布尔值邪恶的场景之一:我强烈建议您进行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 回答