具有心跳的套接字编程不断失去同步

时间:2019-02-15 20:23:16

标签: c# sockets design-patterns

我有一个通过com端口连接的设备,它具有3个功能:

  • 我必须承认的心跳
  • 状态检查
  • 开始设备操作

当设备向我发送心跳信号时,我向设备发送的下一条消息必须始终为确认,否则设备将不响应。

问题,我遇到的问题是,我的应用程序在收到StartDevice之后会不时地发送StatusCheckHeartbeat命令分开

我该如何解决这个问题?

我在下面编写了一个简单的代码版本:

public class MyDevice {

    ComPort comPort;
    Timer statusTimer;

    public MyDevice() {
        //Create a socket connection to the device
        comPort = new ComPort("COM5");
        comPort.Recieve += RecieveSomeData;
        comPort.Open();
        //Start an update timer every 5 mins
        statusTimer = new Timer();
        statusTimer.Tick += StatusTimerTick;
        statusTimer.Start(5);
    }

    public void StartDevice() {
        comPort.Send("Start Device Operation!");
    }

    protected void StatusTimerTick() {
        comPort.Send("What is your status?");
    }

    protected void RecieveSomeData(string data) {
        //if the device sends heart beat, send acknowledgment back
        if (data.StartsWith("Heartbeat")) {
            comPort.Send("Acknowledgement!");
        }
        //if the device is replying to status or 
        // a start operation then tell the consumer
        else {
            ReportStatus(data);
        }
    }

    private void ReportStatus(string data) {
        throw new NotImplementedException();
    }
}

1 个答案:

答案 0 :(得分:0)

您描述的协议容易产生种族冲突。设备可能会在应用程序发送StatusTimerTick的同时发送心跳请求。在这种情况下,即使在您的应用收到心跳请求之后立即发送了此响应,设备也将在接收到心跳响应之前先接收StatusTimerTick。

解决问题的唯一方法是重新设计协议或期望值。重新设计最简单的方法是,心跳响应仍必须跟在每个心跳请求之后,但是之间可能还会收到其他消息,例如StatusTimerTick。如果这太复杂了,您可以重新设计协议,以便您的应用程序仅在设备显式请求信息时发送某些内容,而在没有此类请求的情况下不发送信息。