C#Socket通信,解决粘包和分包问题

2023.8.20 更新

更加完整的代码已经上传到github,EasyTcpSocket,包含socket框架和完整的客户端服务端示例,框架用的.net 6.0,不过和Framework的写法也没什么区别。

还是那句话,边学边做的,仅供参考,切勿用于生产环境。


源码下载,学习的时候做的,现在可以做到一个服务端对应多个客户端同时接受消息,也解决了分包和粘包的问题,欢迎下载

(16条消息) 网络通信编程学习.7z-C#文档类资源-CSDN文库https://download.csdn.net/download/Trinity_Force/44900216

什么是粘包分包

  1. TCP是面向连接的协议
  2. TCP是点到点的通信
  3. TCP提供可靠的传输服务
  4. TCP协议提供全双工的通信
  5. TCP协议面向字节流进行传输的,可以对用户的数据进行拆分或合并

        TCP协议是面向字节流传输的,TCP协议会保证字节流传输时顺序不会改变,不会丢失内容,但是TCP协议会灵活的拆分或者合并用户Socket.Send(buffer)出来的内容,将小的数据整合发送或者是将大的数据拆开发送。

        所以在实际的编程中就会出现服务端一次Receive就收到了客户端多次Send的数据(“粘包”),或者是客户端只Send了一次,服务端却要多次Receive才能完整接收。

粘包示例:客户端发送了一万条“Hello”到服务端,结果服务端收到的是这样的

分包示例:客户端发送了一大串“a”到服务端,结果服务端是分三次收到的。

 解决方法

自己自定义报文格式,发送时根据固定的格式封包,接收时再按照这个格式解包

1 数据包首部添加数据包长度

接收到数据时,先解析首部的“数据包长度”,再解析数据包内容,如果数据包内容的长度不足数据包首部规定的长度,则认为出现了“分包”,需要等待接收下一个数据包,直到传输完整。如果数据包内容的长度大于数据包首部规定的长度,则出现了“粘包”需要认为将粘包分开。

2 数据包结尾添加固定的分隔符

接收到数据后,如果出现结尾标识,则人为将粘包分开,如果一个包中没有结尾标识,则认为出现了“分包”,需要等待下一个数据包,直到出现结尾标识

客户端发送时的封包方法

private void BtnSend_Click(object sender, EventArgs e)
        {
            byte[] dataToBeSend = GetSendData(TextSendData.Text.Trim());
            if (int.TryParse(textRepeatTimes.SelectedItem.ToString(), out int times))
            {
                int dataSize = 0;
                for (int i = 0; i < times; i++)
                {
                    dataSize += ClientSocket.Send(dataToBeSend);
                }
                ShowReceiveDataWithDelegate($"共发送{dataSize}字节的数据");
            }
        }

        private byte[] GetSendData(string text)
        {
            //数据包内容
            byte[] content = Encoding.Default.GetBytes(text);
            //数据包头部
            byte[] header = new byte[4];
            ConvertIntToByteArray(content.Length, ref header);
            //最终封装好的数据包,数据包首位 0 消息 1 文件,2-5位 数据长度
            byte[] dataToBeSend = new byte[content.Length + 5];
            dataToBeSend[0] = 0;
            Array.Copy(header, 0, dataToBeSend, 1, header.Length);
            Array.Copy(content, 0, 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值