我有一个从套接字读取的简单程序。通常它运作良好。但有时接收读取已经读取的2个字节。消息的结构是 1字节头,3字节msgLength,msgLength字节msg,字节尾部。 我使用WireShark记录流量,看起来很好。
问题如下:
packet X = ........ endOfPreviousMessage, trailer byte, header byte, first byte of msgLength packet X+1 = 2 bytes the rest of the msgLength
它正确读取msgLength
(值为253)再次读取53!和消息。当然,这会给消息解析器带来问题。
代码:
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);
}
}
}
答案 0 :(得分:3)
嗯,你的代码中有一个错误,首先是:
int read = CAMSocket.Receive(hdrBuffer,4,SocketFlags.None);
if (read == 0)
{
Logger.Warn(" disconnecting");
Active = false;
break;
}
int msgLength = Utils.BytesToInt(hdrBuffer, 1, 3);
如果read
是1,2或3怎么办?您可能没有读取所有4个字节。这不太可能,但可能。如果消息长度与上一条消息的长度相同,您将看到完全您正在描述的行为。 (对每组头字节使用一个新的字节数组可能会更好,那么你就不会重用“旧”数据,这可能会造成混淆。)
我非常非常怀疑这是.NET套接字实现中的一个错误。
为了诊断,您始终可以将每次调用的返回值记录到Read
,甚至可能记录已读取的数据。