C#同步TCP客户端套接字无法解释的缺失数据

时间:2011-09-28 02:26:45

标签: c# sockets c#-3.0 tcpclient

我在不可靠的移动数据连接上使用TCP,这可能会因干扰或信号强度可能出现的任何问题而丢弃数据包。

重要的是我使用的是Modbus TCP,而另一端的移动路由器将其转换为Modbus RTU(串行),以便与基于串行的设备(从设备)进行通信。

此外,每当向串行设备发送读取请求时,一旦发送响应,其内部指针就会递增到下一个数据块。串口设备不知道移动连接是否仍然正常;如果响应没有一直回到服务器,那么无论如何它都已经增加了它的内部指针。

换句话说,请采取以下方案:

  1. 服务器通过TCP发送modbus读取请求。
  2. 路由器接收请求并将其传递给串行设备。
  3. 串口设备响应路由器。
  4. 串行设备递增数据指针。
  5. 路由器无法将TCP数据包发送回服务器。
  6. 服务器再次发送读取请求。
  7. 串口设备响应路由器。
  8. 串行设备递增数据指针。
  9. 路由器成功将数据发送回服务器。
  10. 在上面的场景中,您将看到步骤5中的问题导致错过整个数据块,因为串行设备不知道先前的读取操作实际上是失败的。它已经转移到下一个块!通常我会做的是检测这个问题并使用“请求先前数据块”操作来重新请求来自串行设备的先前丢失的数据块。

    这是我的问题:我没有从TCP代码中获得任何异常或错误,即使我将所有内容都包含在SystemException try-catch块中并且我正在检查返回值。

    我仔细查看了我的日志文件,发现请求和响应之间的时间约为1秒,但是在怀疑错过数据块时,时间间隔在2到3秒之间。这表明发生了发送,但没有收到任何数据,因此它再次尝试。但当然,当它再次尝试时,串行设备已经将其数据指针增加到下一组数据。

    由于某种原因,串行设备收到了读取请求,但数据从未返回服务器。

    我不是TCP / IP专家,所以有人知道会发生什么吗? TCP是否有可能在“引擎盖下”重新发送数据包而不会导致异常并且我不知道?

    在我的代码中,我只是做这样的事情:

    _log.Debug(string.Format("[{0}]: Sending sync response ({1}).", 
        this._IP.ToString(), CoreUtils.PayloadToString(write_data)));
    
    tcpSynCl.Send(write_data, 0, write_data.Length, SocketFlags.None);
    int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 
                   tcpSynClBuffer.Length, SocketFlags.None);
    
    byte function = tcpSynClBuffer[7];
    byte[] data;    
    
    if (result == 0) throw SystemException("No data received");
    
    // ... process log buffer ...
    
    _log.Debug(string.Format("[{0}]: Got sync response ({1}).", 
        this._IP.ToString(), CoreUtils.PayloadToString(data)));
    
    return data;
    

    没有抛出异常,这表明发动机()和接收()之间发生了一些事情。两个调试日志条目之间的时间是所有其他条目的两倍。可能或不可能?

2 个答案:

答案 0 :(得分:1)

首先:接收0字节并不意味着您没有收到任何内容。这意味着连接已关闭。

第二:由于Nagle算法,你很可能会同时收到两条消息。您需要浏览收到的字节并查看其中的消息。 TCP不是基于消息的,而是基于流的。

答案 1 :(得分:0)

TCP的重点是使流对应用程序透明。丢失的数据包由TCP而不是应用程序处理。如果TCP没有获得给定数据包的ACK,它将尝试重新发送数据包。它最终将停止发送任何其他数据包并继续重新发送丢失的数据包,直到它收到并确认或连接超时。

接收方类似。如果数据包丢失,TCP堆栈将不会向应用程序发送任何数据,直到它收到丢失的数据包。 TCP还保证数据包顺序。丢失的数据包将导致接收器停止,直到它丢失数据包或超时。

接收方将接收并缓冲丢弃数据包之后的一些数据包,并在收到丢失的数据包后“播放它们”。