问题:
当我做这样的事情时:
for (int i = 0; i < 100; i++)
{
SendMessage( sometSocket, i.ToString());
Thread.Sleep(250); // works with this, doesn't work without
}
Run Code Online (Sandbox Code Playgroud)
无论有没有睡眠,服务器都会记录发送单独的消息.但是,如果没有睡眠,客户端最终会在单个OnDataReceived中接收多条消息,因此客户端将收到以下消息:
0,1,2,34,5,678,9 ......
服务器发送代码:
private void SendMessage(Socket socket, string message)
{
logger.Info("SendMessage: Preparing to send message:" + message);
byte[] byteData = Encoding.ASCII.GetBytes(message);
if (socket == null) return;
if (!socket.Connected) return;
logger.Info("SendMessage: Sending message to non " +
"null and connected socket with ip:" + socket.RemoteEndPoint);
// Record this message so unit testing can very this works.
socket.Send(byteData);
}
Run Code Online (Sandbox Code Playgroud)
客户收到代码:
private void OnDataReceived(IAsyncResult asyn)
{
logger.Info("OnDataReceived: Data received.");
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.Socket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(theSockId.DataBuffer, 0, iRx, chars, 0);
System.String szData = new System.String(chars);
logger.Info("OnDataReceived: Received message:" + szData);
InvokeMessageReceived(new SocketMessageEventArgs(szData));
WaitForData(); // .....
Run Code Online (Sandbox Code Playgroud)
套接字包:
public class SocketPacket
{
private Socket _socket;
private readonly int _clientNumber;
private byte[] _dataBuffer = new byte[1024]; ....
Run Code Online (Sandbox Code Playgroud)
我的预感是它与缓冲区大小有关,或者只是在OnDataReceived和EndReceive之间我们得到了多条消息.
更新:当我在OnDataReceived的开头放置一个Thread.Sleep时,它会得到每条消息.唯一的解决方案是将此消息包装在长度前缀和字符串中以表示结束吗?
Tim*_*mwi 11
这是预期的行为.TCP套接字表示线性字节流,而不是一系列分隔良好的"数据包".您不能假设您收到的数据与发送时的数据相同.
请注意,这有两个后果:
必须编写代码来处理这两种情况,否则会出现错误.