Unity Socket学习笔记 (三)TCP&UDP

文章目录


一、TCP与UDP协议特点

1、TCP协议特点

特点 说明
面向连接 通信前需通过三次握手建立连接,确保双方准备就绪
可靠性‌ 通过序列号、确认应答、超时重传等机制保证数据完整有序到达
‌流量控制‌ 自动调整传输速率避免网络拥塞
适用场景‌ 卡牌类、棋牌类、回合制等对数据完整性要求高的游戏

2、UDP协议特点

特点 说明
无连接 通信前需通过三次握手建立连接,确保双方准备就绪
高效性‌ 通过序列号、确认应答、超时重传等机制保证数据完整有序到达
‌不可靠 自动调整传输速率避免网络拥塞
适用场景‌ 实时性要求高的游戏如FPS、MOBA等

3、协议对比

特性 TCP UDP
连接方式 面向连接 无连接
可靠性 高 低
传输速度 较慢 快
数据顺序 保证 不保证
流量控制 有 无
头部大小 20字节 8字节
使用场景 数据完整性优先 实时性优先

二、TCP与UDP协议实现

1、TCP通信实现

1、TCP服务端实现

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

class TCPServer
{
    static void Main()
    {
        // 1. 创建TCP Socket
        Socket tcpServer = new Socket(AddressFamily.InterNetwork, 
                                    SocketType.Stream, 
                                    ProtocolType.Tcp);
        
        // 2. 绑定IP和端口
        IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
        tcpServer.Bind(endpoint);
        
        // 3. 开始监听
        tcpServer.Listen(10);
        Console.WriteLine("服务器启动完成");
        
        // 4. 接受客户端连接
        Socket clientSocket = tcpServer.Accept();
        Console.WriteLine("客户端已连接");
        
        // 5. 接收数据
        byte[] data = new byte[1024];
        int length = clientSocket.Receive(data);
        string message = Encoding.UTF8.GetString(data, 0, length);
        Console.WriteLine("收到消息: " + message);
        
        // 6. 发送数据
        clientSocket.Send(Encoding.UTF8.GetBytes("服务器已收到"));
        
        // 7. 关闭连接
        clientSocket.Close();
        tcpServer.Close();
    }
}

2、TCP客户端实现

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

class TCPClient
{
    static void Main()
    {
        // 1. 创建TCP Socket
        //SocketType.Stream 对应面向连接的TCP协议
        Socket tcpClient = new Socket(AddressFamily.InterNetwork, 
                                    SocketType.Stream, 
                                    ProtocolType.Tcp);
        
        // 2. 连接服务器
        tcpClient.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888));
        
        // 3. 发送数据
        tcpClient.Send(Encoding.UTF8.GetBytes("Hello Server"));
        
        // 4. 接收响应
        byte[] data = new byte[1024];
        int length = tcpClient.Receive(data);
        Console.WriteLine("服务器响应: " + Encoding.UTF8.GetString(data, 0, length));
        
        // 5. 关闭连接
        tcpClient.Close();
    }
}

2、UDP通信实现

1、UDP服务端实现

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

class UDPServer
{
    static void Main()
    {
        // 1. 创建UDP Socket
        // SocketType.Dgram 对应无连接的UDP协议
        Socket udpServer = new Socket(AddressFamily.InterNetwork,
                                    SocketType.Dgram,
                                    ProtocolType.Udp);
        
        // 2. 绑定端口
        udpServer.Bind(new IPEndPoint(IPAddress.Any, 8889));
        Console.WriteLine("UDP服务器已启动");
        
        // 3. 接收数据
        //UDP接收响应‌必须‌有端口号,但可通过设为0由系统自动分配
        EndPoint clientEnd = new IPEndPoint(IPAddress.Any, 0);
        byte[] data = new byte[1024];
        int length = udpServer.ReceiveFrom(data, ref clientEnd);
        string message = Encoding.UTF8.GetString(data, 0, length);
        Console.WriteLine($"收到来自{clientEnd}的消息: {message}");
        
        // 4. 发送响应
        udpServer.SendTo(Encoding.UTF8.GetBytes("UDP服务器已收到"), clientEnd);
        
        // 5. 关闭Socket
        udpServer.Close();
    }
}

2、UDP客户端实现

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

class UDPClient
{
    static void Main()
    {
        // 1. 创建UDP Socket
        Socket udpClient = new Socket(AddressFamily.InterNetwork,
                                    SocketType.Dgram,
                                    ProtocolType.Udp);
        
        // 2. 发送数据
        IPEndPoint serverEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8889);
        udpClient.SendTo(Encoding.UTF8.GetBytes("Hello UDP Server"), serverEnd);
        
        // 3. 接收响应
        //UDP接收响应‌必须‌有端口号,但可通过设为0由系统自动分配
        byte[] data = new byte[1024];
        EndPoint remoteEnd = new IPEndPoint(IPAddress.Any, 0);
        int length = udpClient.ReceiveFrom(data, ref remoteEnd);
        Console.WriteLine($"收到来自{remoteEnd}的响应: {Encoding.UTF8.GetString(data, 0, length)}");
        
        // 4. 关闭Socket
        udpClient.Close();
    }
}

3、实现对比

特性 TCP实现 UDP实现
Scoket创建 SocketType.Stream,ProtocolType.Tcp SocketType.Dgram,ProtocolType.Udp
连接管理 需要Connect()/Accept()建立连接 无连接,直接发送数据
数据传输 Send()/Receive() SendTo()/ReceiveFrom()
错误处理 处理连接中断,超时重传等 主要处理端口不可达等

三、TCPListener与UdpClient

1、TCPListener使用

TCPListener是对Socket的高级封装,简化了TCP服务端的创建过程:

csharp 复制代码
using System.Net;
using System.Net.Sockets;

class TCPListenerExample
{
    static void Main()
    {
        // 1. 创建TCPListener
        TcpListener listener = new TcpListener(IPAddress.Any, 8888);
        listener.Start();
        Console.WriteLine("TCPListener已启动");
        
        // 2. 接受客户端连接
        TcpClient client = listener.AcceptTcpClient();
        Console.WriteLine("客户端已连接");
        
        // 3. 获取网络流
        NetworkStream stream = client.GetStream();
        
        // 4. 读取数据
        byte[] buffer = new byte[1024];
        int bytesRead = stream.Read(buffer, 0, buffer.Length);
        string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
        Console.WriteLine("收到消息: " + message);
        
        // 5. 发送响应
        byte[] response = Encoding.UTF8.GetBytes("TCPListener已收到");
        stream.Write(response, 0, response.Length);
        
        // 6. 关闭连接
        client.Close();
        listener.Stop();
    }
}

2、UDPListener使用

UdpClient是对UDP Socket的高级封装,简化了UDP通信过程:

csharp 复制代码
using System.Net;
using System.Net.Sockets;

class UdpClientExample
{
    static void Main()
    {
        // 1. 创建UdpClient
        UdpClient udpClient = new UdpClient(8888);
        Console.WriteLine("UdpClient已启动");
        
        // 2. 接收数据
        IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
        byte[] receivedData = udpClient.Receive(ref remoteEP);
        string message = Encoding.UTF8.GetString(receivedData);
        Console.WriteLine($"收到来自{remoteEP}的消息: {message}");
        
        // 3. 发送响应
        byte[] response = Encoding.UTF8.GetBytes("UdpClient已收到");
        udpClient.Send(response, response.Length, remoteEP);
        
        // 4. 关闭UdpClient
        udpClient.Close();
    }
}

3、与Socket的对比

1、选择建议

1、使用TCPListener/UdpClient便于快速开发,适用简单通信需求,不需要特殊的Socket配置。

2、使用原生Socket需要精细控制网络行为,实现自定义协议,需要设置特殊Socket选项

2、实际应用建议

游戏类型选择:

回合制,卡牌类游戏优先选择TCP

实时动作类游戏优先选择UDP'

混合使用:

关键数据(如玩家状态)使用TCP

实时数据(如位置更新)使用UDP

相关推荐
2501_9269783344 分钟前
给自指系统接一个外部锚 —— 一个关于「用 AI 观察自己」的方法
人工智能·经验分享·笔记·机器学习·ai写作
li星野1 小时前
DO — Auxiliary Verb (One-Page Notes)
学习
minglie11 小时前
关系的有向管道模型
学习
~kiss~3 小时前
LangChain 基础学习
学习·langchain
一木 之林3 小时前
提示词工程学习总结:用 Few-shot 把大模型调教成金融文本分类、抽取与匹配的自动化流水线
人工智能·学习·计算机视觉·金融·分类
传奇开心果编程3 小时前
【Compose Multiplatform 跨端开发学与练】第7课 平台适配与互操作
android·windows·学习·ui·ios·kotlin·composer
我命由我123454 小时前
Photoshop - Photoshop 使用对齐功能定位元素
学习·职场和发展·产品运营·求职招聘·职场发展·产品经理·学习方法
AOI小白新手上路5 小时前
anomalib 缺陷检测复现笔记:从跑通库到 EfficientAD 落地
人工智能·笔记·机器学习
阳光九叶草LXGZXJ5 小时前
达梦数据库-报错-16-MERGE INTO提示:无效的列名[XX]
linux·运维·数据库·sql·学习
xxwl5855 小时前
RabbitMQ 学习笔记
笔记·学习·rabbitmq