C#中处理Socket粘包

在C#中使用Socket进行网络通信时,粘包问题是常见的。粘包问题通常发生在TCP协议中,因为TCP是流式协议,数据可能会被分割成多个包发送,也可能多个小包会被合并成一个大包接收。

处理粘包问题的常见方法是使用消息分隔符或消息长度前缀。以下是使用消息长度前缀来处理粘包问题的示例代码。

发送端代码

在发送端,每条消息的前面加上一个固定长度的消息长度前缀。

cs 复制代码
using System;
using System.Net.Sockets;
using System.Text;

public class Client
{
    public static void SendMessage(Socket socket, string message)
    {
        byte[] messageBytes = Encoding.UTF8.GetBytes(message);
        byte[] lengthPrefix = BitConverter.GetBytes(messageBytes.Length);

        byte[] packet = new byte[lengthPrefix.Length + messageBytes.Length];
        Buffer.BlockCopy(lengthPrefix, 0, packet, 0, lengthPrefix.Length);
        Buffer.BlockCopy(messageBytes, 0, packet, lengthPrefix.Length, messageBytes.Length);

        socket.Send(packet);
    }
}

接收端代码

在接收端,首先读取消息长度前缀,然后根据长度前缀读取完整的消息。

cs 复制代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class Server
{
    private const int LengthPrefixSize = 4;

    public static void StartListening()
    {
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 11000);
        Socket listener = new Socket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(10);

            while (true)
            {
                Socket handler = listener.Accept();
                ProcessClient(handler);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void ProcessClient(Socket handler)
    {
        byte[] buffer = new byte[1024];
        int bytesRead = 0;

        while (true)
        {
            // Read the length prefix
            bytesRead = handler.Receive(buffer, 0, LengthPrefixSize, SocketFlags.None);
            if (bytesRead == 0)
                break;

            int messageLength = BitConverter.ToInt32(buffer, 0);

            // Read the message
            int totalBytesRead = 0;
            byte[] messageBuffer = new byte[messageLength];
            while (totalBytesRead < messageLength)
            {
                bytesRead = handler.Receive(messageBuffer, totalBytesRead, messageLength - totalBytesRead, SocketFlags.None);
                if (bytesRead == 0)
                    break;

                totalBytesRead += bytesRead;
            }

            string message = Encoding.UTF8.GetString(messageBuffer);
            Console.WriteLine("Received: {0}", message);
        }

        handler.Shutdown(SocketShutdown.Both);
        handler.Close();
    }
}

解释

  • 发送端:
  • 将消息转换为字节数组。
  • 计算消息的长度,并将长度作为前缀添加到消息前面。
  • 发送带有长度前缀的消息。
  • 接收端:
  • 首先读取固定长度的消息长度前缀。
  • 根据长度前缀读取完整的消息。
  • 将消息转换为字符串并处理。

通过这种方式,可以有效地解决TCP通信中的粘包问题。

相关推荐
猿的天空13 分钟前
机器人双手迎来全栈训练系统:灵初智能EgoSteer让灵巧手无所不能
网络·人工智能·计算机·ai·程序员·机器人·编程
Xzaveir_77719 分钟前
OPPO、vivo、荣耀号码认证:多终端拨测矩阵与异常复现
大数据·网络·科技·矩阵·产品经理·ai-native
wuqingshun31415924 分钟前
从网络角度来看,用户从输入网址到网页显示,期间发生了什么?
网络
牛马工作号38 分钟前
Zigbee 专业详解:从协议到排障
网络·物联网·安全
牛马工作号1 小时前
Wi‑Fi 完全指南:从 802.11 协议到 Wi‑Fi 7、AC+AP 与 Mesh 工程组网
网络·网络协议·智能路由器
智慧光迅AINOPOL1 小时前
智慧工厂全光网怎么扛住AGV与强电磁?光电复合缆与工业级方案
网络·全光网解决方案·全光网·酒店全光解决方案·泛住宿全光网解决方案
JoyCong19982 小时前
手机变身“司令台”!ToDesk AI安卓版上线
网络·人工智能·科技·智能手机·电脑·远程工作·远程操作
a4493153622 小时前
iPhone 基带故障诊断——无服务/搜索不到网络的芯片级维修实录
网络·macos·ios·电脑·iphone
Xzaveir_7773 小时前
企业号码负面标记治理:认证、申诉与合规事件的三轨模型
大数据·网络·人工智能·科技·产品经理
代码AC不AC3 小时前
【Linux】Socket编程TCP
linux·tcp·socket编程