本文主要介绍下,如果不进行组包的时候,会出现什么情况: 下面是服务端,一次性发送1000条数据:
public void AddProtocolMessage()
{
Google.Protobuf.Examples.Person.Person person = new Google.Protobuf.Examples.Person.Person();
person.Id = 1;
person.Name = "xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axxiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好a你好aiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a" +
"xiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好axiaoming你好a你好a";
person.Email = "xiaoming@163.com";
Google.Protobuf.Examples.Person.Person.Types.PhoneNumber phoneNumber = new Google.Protobuf.Examples.Person.Person.Types.PhoneNumber();
phoneNumber.Number = "123456";
phoneNumber.Type = Google.Protobuf.Examples.Person.Person.Types.PhoneType.Mobile;
person.Phones.Add(phoneNumber);
MemoryStream ms = new MemoryStream();
Google.Protobuf.CodedOutputStream codedOutput = new Google.Protobuf.CodedOutputStream(ms);
person.WriteTo(codedOutput);
codedOutput.Flush();
byte[] buffer = ms.GetBuffer();
long len = ms.Length;
Message message = new Message();
message.m_data = buffer;
for (int i = 0; i < 1000; ++i)
{
m_sendMessages.Enqueue(message);
}
}
客户端在接收的地方:
static int count = 0;
static int totalSize = 0;
private void OnReceiveCallback(IAsyncResult ar)
{
Socket sock = (Socket)ar.AsyncState;
int len = sock.EndReceive(ar);
totalSize += len;
Console.WriteLine("receive=" + count++ + " len=" + len + " totalSize=" + totalSize);
m_clientSocket.BeginReceive(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, OnReceiveCallback, m_clientSocket);
}
这里的m_receiveBuffer我们开的是128 服务器总共发送了1000次,而客户端接收了13204次,最后一次接收的大小是16字节。总量是不变的。1690000字节。
而我们的协议呢?是1690个字节,所以在接收的地方,要将多次接收到的数据组装成一个有效的数据包才行。
那我们想,如果是不是buffer开的大一点,就好了,于是我们开成4096个字节大小。
服务端发送了1000次,但是客户端本次接收了964次,咦? 接收的次数小于了发送的次数,那说明,比如有一次接收的字节数大于发送的字节数1690个字节。 果然,红色框内接收的字节数大于发送的1690个字节。
所以这就说明了,buffer开的大和开的小,都不能准确的定义,一次接收的数据就是一个完整的包,有可能是大于一个包,也可能是小于一个包。 故,必须标记一个包的大小,然后根据包的大小去组装成一个有效包。
|