开发者

C# synchronous TCP client socket unexplained missing data

I'm using TCP over an unreliable mobile data connection, which may drop packets due to interference or whatever may be going wrong with the signal strength.

What complicates matters is that I'm using Modbus TCP and the mobile router on the other end converts this into Modbus RTU (Serial) in order to communicate with a serial based device (slave).

Furthermore, whenever a read request is sent to the serial device its internal pointer will be incremented to the next chunk of data as soon as the response has been sent. The serial device will have no idea whether the mobile connection is still OK; if the response does not make it all the way back to the server it will already have incremented its internal pointer anyway.

In other words take the following scenario:

  1. Server sends modbus read request over TCP.
  2. Router receives request and passes it to serial device.
  3. Serial device responds to router.
  4. Serial device increments data pointer.
  5. Router fails to send TCP packet back to server.
  6. Server sends read request again.
  7. Serial device responds to router.
  8. Serial device increments data pointer.
  9. Router send data back to server successfully.

In the above scenario you will see that the problem in step 5 causes a whole data chunk to be missed, because the serial device has no idea that the previous read operation actually failed. It has already moved on to the next chunk! Normally what I would do is detect this problem and use the "request previous data chunk" operation to re-request the previously missed data chunk from the serial device.

Here is my problem: I'm not getting any exceptions or errors from the TCP code even though I have everything enclosed in a SystemException try-catch block and I'm checking the return value.

I looked through my log file carefully and noticed that the time between a request and a response is about 1 second, however at the time of the suspected missed data chunk, the time gap was between 2 and 3 seconds. This would suggest that a send occured, but no data was received so it tried again. But of course when it tried again, the serial device would have already incremented its data pointer to the next set of data.

For some reason the serial device received the read request, howeve开发者_高级运维r the data never made it back to the server.

I'm not an expert on TCP/IP, so does anyone out there know what could have happened? Is it possible for TCP to resend packets "under the hood" without causing exceptions and without me knowing?

In my code I'm simply doing something like this:

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

There were no exceptions thrown, which would suggest that something happened between Send() and Receive() under the hood. The time between the two debug log entries was twice as long than all the others. Possible or not possible?


First of all: Receiving 0 bytes do not mean that you haven't received anything. It means that the connection has been closed.

Second: It's likely that you'll receive two messages at the same time due to Nagle algorithm. You need to go through the received bytes and see how messages there are in there. TCP is not message based but stream based.


The whole point of TCP is to make the stream transparent to the application. Lost packets are handled by TCP and not the application. If TCP does not get an ACK for a given packet, it will attempt to resend the packet. It will eventually stop sending any other packets and continue to resend that lost packet until it receives and ACK or the connection times out.

Similar on the receiving side. If a packet is lost, the TCP stack will not send any data to the application until it receives the missing packet. TCP also guarantees packet order. A lost packet will cause the receiver to stop until it either gets the missing packet or times out.

The receiver will accept and buffer some of the packets that came after the dropped packet and "play them back" once the missing packet is received.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜