在下面的代码中,状态是一个具有msgLength属性的对象,它是消息的总长度.msgLength是消息的前四个字节。 当在“快速”连续中收到多条消息时,我在state.msgLength属性中得到意外结果。当state.msglength不符合预期时 我试图收到错误。指定的参数超出了有效值的范围。
StateObj state = (StateObj)ar.AsyncState;
try
{
state.read += state.socket.EndReceive(ar);
if (state.read == 0)
{
state.socket.Close();
state.socket.Dispose();
state.socket = null;
this.Invoke((MethodInvoker)delegate { listBox1.Items.Add(DateTime.Now.ToString("HH:mm ss") + " socket closed"); });
return;
}
}
catch (Exception)
{
this.Invoke((MethodInvoker)delegate { listBox1.Items.Add(DateTime.Now.ToString("HH:mm ss") + " socket closed"); });
return;
}
if (state.read < 4)
{
//read again you dont have state,msglength
state.socket.BeginReceive(state.dataBuffer, state.read, 4 - state.read, 0, cbReceive, state);
}
else
{
state.msglength = BitConverter.ToInt32(state.dataBuffer, 0);
}
if (state.read < state.msglength)
{
//read again you dont have the complete message
//here is the error Specified argument was out of the range of valid values.
state.socket.BeginReceive(state.dataBuffer, state.read, state.msglength - state.read, 0, cbReceive, state);
}
else
{
//process here
if (state.read > state.msglength )
{
state.read = state.read - state.msglength;
}
else
{
state.read = 0;
}
state.socket.BeginReceive(state.dataBuffer, 0, state.dataBuffer.Length, 0, cbReceive, state);
}
答案 0 :(得分:0)
我认为 state.socket.BeginReceive 执行两次。 因为当它正在读取它的标题时, if(state.read&lt; 4)和 if(state.read&lt; state.msglength)都为真。在第一个 state.socket.BeginReceive之后返回( ..可以解决问题。
if (state.read < 4)
{
//read again you dont have state,msglength
state.socket.BeginReceive(state.dataBuffer, state.read, 4 - state.read, 0, cbReceive, state);
return; // <------
}
else
{
state.msglength = BitConverter.ToInt32(state.dataBuffer, 0);
}
if (state.read < state.msglength)
{
//read again you dont have the complete message
//here is the error Specified argument was out of the range of valid values.
state.socket.BeginReceive(state.dataBuffer, state.read, state.msglength - state.read, 0, cbReceive, state);
}
else
{
state.read = 0;
//process correctly expected message
}
我想我发现了另一个问题,如果消息中指定的messageLength只是数据的大小。您应该阅读 if(state.read&lt; state.msglength + 4)因为长度标头包含在您的缓冲区中。
我主要是分割阅读标题/数据。喜欢:(PSEUDO)
byte[] header;
byte[] buffer;
int bytesRead;
public void ReadHeader()
{
bytesNeeded = 4;
bytesRead = 0;
BeginReadHeader();
}
public void BeginReadHeader()
{
BeginReceive(header, bytesRead, bytesNeeded-bytesRead, EndReadHeader);
}
public void EndReadHeader()
{
int read = EndReceive();
if(read == 0)
{
CloseSocket();
return;
}
bytesRead += read;
if(bytesRead == byteNeeded)
ReadData();
else
BeginReadHeader();
}
public void ReadData()
{
bytesNeeded = BitConverter.ToInt32(header, 0);
bytesRead = 0;
if(buffer.Length < bytesNeeded)
buffer = new byte[bytesNeeded];
BeginReadData();
}
public void BeginReadData()
{
BeginReceive(buffer, bytesRead, bytesNeeded-bytesRead, EndReadData);
}
public void EndReadData()
{
int read = EndReceive();
if(read == 0)
{
CloseSocket();
}
bytesRead += read;
if(bytesRead == byteNeeded)
{
HandleData();
}
else
BeginReadData();
}
public void HandleData()
{
// handle data in buffer. BinaryReader
ReadHeader();
}