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

相关推荐
何以解忧唯有撸码1 小时前
c# + YOLODotNet+OpenCVSharp 实现物品轨迹追踪
计算机视觉·c#·winform·yolov8·opencvsharp
zhangrelay3 小时前
新版|-|单片机原理与接口技术-2026持续改进优化-从MEGA2560-ESP32与Wokwi到ROS2-Lyrical与具身智能栈
笔记·单片机·嵌入式硬件·学习
Jimmy4 小时前
深夜突袭:我们的午夜战场
笔记·产品·电子书
志尊宝6 小时前
AI原生前端开发(025):端侧AI实战项目:智能笔记助手
人工智能·笔记·ai-native
lll23526917797 小时前
线下多人发言对比与录音操作
笔记·智能手机
叼烟扛炮7 小时前
Linux 学习笔记(三十三):线程互斥——互斥锁(Mutex)与死锁
linux·运维·服务器·笔记·学习·1024程序员节
m4Rk_9 小时前
【论文阅读】Agent 记忆机制(113):Agentic Memory Management——从“检索相关信息”走向“管理 Agent 内部记忆”
论文阅读·人工智能·学习·开源·github
凯基迪科技10 小时前
Unity游戏加密锁逆向方案、选型与攻防分析
游戏·unity·游戏引擎
深圳老胡10 小时前
STM32C5A3ZG 网络调试总结:从启动失败到连续 Ping 稳定
笔记·stm32·单片机·代码规范
辣知10 小时前
辣知·化智92 《山海经》里的史前密码
学习