Reputation: 71
I have a simple program that reads from the socket. Normally it works well. but sometimes The receive is reading 2 bytes that is already read. The structure of the message is 1 byte header, 3 bytes msgLength, msgLength bytes msg, byte trailer. I record the traffic with WireShark and it seems fine.
The problem occurs as follows:
packet X = ........ endOfPreviousMessage, trailer byte, header byte, first byte of msgLength packet X+1 = 2 bytes the rest of the msgLength
It reads the msgLength
correctly (the value is 253) The is read the 53 again! and the message. This, of course, are causing problem to the message parser.
the code:
Socket CAMListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
CAMListenSocket.Bind(new IPEndPoint(IPAddress.Any,CAMListenPort));
CAMListenSocket.Listen(10);
CAMSocket = CAMListenSocket.Accept();
internal void CAMSocketReceive()
{
byte[] hdrBuffer = new byte[4];
while (Active)
{
try
{
int read = CAMSocket.Receive(hdrBuffer,4,SocketFlags.None); //Reading the first 4 bytes
if (read == 0)
{
Logger.Warn(" disconnecting");
Active = false;
break;
}
int msgLength = Utils.BytesToInt(hdrBuffer, 1, 3); //Convert to int, skipping the first byte (which is the SOH)
if (hdrBuffer[0] != 1)
{
Logger.Warn("CAMSocketReceive:: Out of sync first byte is not SOH !! Handling recovery " );
//handleRecovery();
}
msgLength = msgLength + 1;//Add the trailer
byte[] rawMsg = new byte[msgLength]; //Prepare a buffer to hold the CAM msg
read = 0;
do
{
read+= CAMSocket.Receive(rawMsg, read, msgLength - read, SocketFlags.None); //Read MSG_LENGTH bytes.
} while (read < msgLength);
CAMMessage cam = new CAMMessage(rawMsg); //parse the message
CAMQueue.Add(cam); //Add to the CAM queue
}
catch (Exception ex)
{
Logger.Error("Error while reading from CAM socket: ", ex);
}
}
}
Upvotes: 0
Views: 469
Reputation: 1499900
Well, you've got one bug in your code here, to start with:
int read = CAMSocket.Receive(hdrBuffer,4,SocketFlags.None);
if (read == 0)
{
Logger.Warn(" disconnecting");
Active = false;
break;
}
int msgLength = Utils.BytesToInt(hdrBuffer, 1, 3);
What if read
is 1, 2 or 3? You may not have read all 4 bytes. It's unlikely, but possible. If the message length is the same as for the previous message, you'd see exactly the behaviour you're describing. (It would probably be better to use a new byte array for each set of header bytes, then you wouldn't be reusing the "old" data, which could be causing confusion.)
I very much doubt that this is a bug in the .NET socket implementation.
For the sake of diagnostics, you could always log the return value of each call to Read
, and possibly even the data that's been read.
Upvotes: 3