TCP是基于流的协议。要将该流转换为我的消息,我将使用消息本身发送每条消息的大小。在服务器端,我首先读取消息的前两个字节,它们具有大小。然后我创建一个字节数组,其大小等于刚刚读取的大小。然后我将字节读入该数组。但由于某种原因,读取的字节数多于指定的字节数。如何读取与指定的字节数完全相同的字节数?
这是我的代码:
while (true)
{
data = null;
length = null;
size = new byte[2];
handler.Receive(size);
length += Encoding.ASCII.GetString(size, 0, 2);
System.Console.WriteLine("Size: " + Int32.Parse(length));
bufferSize = Int32.Parse(length) + 2;
bytes = new byte[bufferSize];
handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bufferSize);
System.Console.WriteLine("Data: " + data);
}
这是我在Windows PC上运行的服务器,用C#编写。我的客户端运行在用Java编写的Android手机中。
答案 0 :(得分:3)
不清楚为什么你要添加两个已经传输的大小 - 你已经考虑了在你之前接收时存储长度的两个额外字节。所以我摆脱了+2
。
您还需要尊重您的问题中已经陈述的事实 - TCP是一个字节序列,而不是消息。因此,您永远无法保证对Receive
的调用是否会检索整个"消息"或者只是其中一部分(或者,可能是多个消息的一部分)。因此,您需要确保尊重Receive
中的返回值。
我们可能会将您的代码重写为:
while (true)
{
data = null;
length = null;
size = ReceiveExactly(handler,2);
length = Encoding.ASCII.GetString(size, 0, 2); //Why +=?
bufferSize = Int32.Parse(length); //Why + 2?
System.Console.WriteLine("Size: " + bufferSize);
bytes = ReceiveExactly(handler,bufferSize);
data += Encoding.ASCII.GetString(bytes, 0, bufferSize);
System.Console.WriteLine("Data: " + data);
}
ReceiveExactly
的定义如下:
private byte[] ReceiveExactly(Socket handler, int length)
{
var buffer = new byte[length];
var receivedLength = 0;
while(receivedLength < length)
{
var nextLength = handler.Receive(buffer,receivedLength,length-receivedLength);
if(nextLength==0)
{
//Throw an exception? Something else?
//The socket's never going to receive more data
}
receivedLength += nextLength;
}
return buffer;
}
答案 1 :(得分:2)
使用方法
接收特定数量的字节Socket.Receive(Byte[], Int32, Int32, SocketFlags)
而不是Socket.Receive(Byte[])
。请参阅规范here
我怀疑你想要像
这样的东西int len = Socket.Receive(bytes, 0, bufferSize, SocketFlags.None);
data += Encoding.ASCII.GetString(bytes, 0, len);
System.Console.WriteLine("Data: " + data);