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通信中的粘包问题。

相关推荐
qianshang2333 小时前
SQL注入学习总结
网络·数据库·渗透
云小逸4 小时前
【网络通信】同一网段与不同网段的通信原理
网络·网络安全
zr5268554476 小时前
PCIe-PN卡(三格电子)
网络
无名的小三轮6 小时前
防火墙基础实验:智能选路下的透明DNS选路配置
网络
一轮弯弯的明月6 小时前
TCP传输大致过程、流量控制与拥塞控制
网络·tcp/ip·计算机网络·学习心得
犀思云6 小时前
如何通过网络即服务平台实现企业数字化转型?
运维·网络·人工智能·系统架构·机器人
皇帝要考研6 小时前
【ISO 13400-2:2019】核心配置项
网络·网络协议
犀思云7 小时前
企业端到端NaaS连接的优势与应用
网络·人工智能·机器人·智能仓储·专线
Godspeed Zhao7 小时前
现代智能汽车系统——总线技术1
网络·汽车·php
JoySSLLian7 小时前
IP SSL证书:一键解锁IP通信安全,高效抵御网络威胁!
网络·人工智能·网络协议·tcp/ip·ssl