TCP无保护消息边界的解决

I_was_a_novice 2014-06-17 02:13:54
最近在看《Visual C#网络编程技术与实践》
看到第2章
2.3 TCP无保护消息边界
2.3.2采用变长的消息 这1小节时有些代码没看明白
------
TCP无保护消息边界的解决
针对这个问题,一般有3种解决方案:
(1)发送固定长度的消息
(2)把消息的尺寸与消息一块发送
(3)使用特殊标记来区分消息间隔
------
(2)、消息长度与消息一同发送
我们可以这样做:通过使用消息的整形数值来表示消息的实际大小,所以要把整形数转换为字节类型。下面是发送变长消息的SendMessage方法。具体代码如下:

private static int SendMessage(Socket s, byte[] msg)
{
int offset = 0;
int sent;
int size = msg.Length;
int dataleft = size;
byte[] msgsize = new byte[2];
//将消息尺寸从整形转换成可以发送的字节型
msgsize = BitConverter.GetBytes(size);

//发送消息的长度信息
sent = s.Send(size);//书上是这样写的,我想应该是sent = s.Send(msgsize);吧
while (dataleft > 0)
{
sent = s.Send(msg, offset, dataleft, SocketFlags.None);
//设置偏移量
offset += sent;
dataleft -= sent;
}
return offset;
}

下面是接收变长消息的ReciveVarMessage方法。代码如下:

private byte[] ReciveVarMessage(Socket s)
{

int offset = 0;
int recv;

//问题开始
//中间的部分没有明白什么意思
//不应该是先接收消息长度消息,将长度消息转换为int类型,根据长度接收发送的消息么
byte[] msgsize = new byte[2];

//将字节数组的消息长度信息转换为整形
int size = BitConverter.ToInt16(msgsize);
int dataleft = size;
byte[] msg = new byte[size];

//接收2个字节大小的长度信息
recv = s.Receive(msgsize, 0, 2, 0);
//问题结束

while (dataleft > 0)
{
//接收数据
recv = s.Receive(msg, offset, dataleft, 0);
if (recv == 0)
{
break;
}
offset += recv;
dataleft -= recv;
}
return msg;
}

谁能详细的解释下接收的函数啊
...全文
281 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
於黾 2014-06-17
  • 打赏
  • 举报
回复
反正我在实际使用中只发现过粘包,从来没有包不完整的情况出现过. 粘包也是因为设备对通信做了优化,能一次发送的数据就不分两次发送了.
penguin_ku 2014-06-17
  • 打赏
  • 举报
回复
tcp消息为何要边界?本身tcp就是有边界的!tcp是滑动窗口传输的,你根本没必要去监测那些消息是不是完整的。除非你是以太网上传输串口数据,这个也只是你自己的业务逻辑问题,与tcp没啥关系
於黾 2014-06-17
  • 打赏
  • 举报
回复
反正我自己测试时根本没用分组接收再重新整合的过程. 客户端发送100W字节,服务端就直接接收到100W字节. 而不是分成好多次去Receive
於黾 2014-06-17
  • 打赏
  • 举报
回复

while (dataleft > 0)              {                 //接收数据                  recv = s.Receive(msg, offset, dataleft, 0);                  if (recv == 0)                  {                      break;                  }                  offset += recv;                  dataleft -= recv;             } 
这里感觉完全不对啊. 两次Receive之间不需要sleep?怎么知道此周期没有接收完毕的数据,下个周期一定能够到达呢? 如果默认发送方没有延时的将所有数据都送到缓冲区里了, 那应该能够一次性获取到所有需要的数据了吧...
於黾 2014-06-17
  • 打赏
  • 举报
回复
没错,书上全部都写反了.按这个代码,size永远为0. 不知道这本书是哪个脑残儿童写的,反正我没看过. 既然代码能够如此错误百出,原理也不见得都是正确的. 果断弃书吧.
I_was_a_novice 2014-06-17
  • 打赏
  • 举报
回复
引用 1 楼 rtdb 的回复:
如此错漏百出,弃书吧
高手,能不能写个完整的接收函数
小白hk 2014-06-17
  • 打赏
  • 举报
回复
学习了,正在学习中
rtdb 2014-06-17
  • 打赏
  • 举报
回复
如此错漏百出,弃书吧

110,552

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧