实现客户端与服务器间简易的UDP同步通信

发布于:2025-03-25 ⋅ 阅读:(29) ⋅ 点赞:(0)

什么是UDP通信

UDP(User Datagram Protocol,用户数据报协议)通信是一种在计算机网络中使用的传输层通信协议,以下是关于它的详细介绍:

  • 基本概念:UDP 是一种无连接的协议,它在数据传输时不需要先建立连接,就可以直接将数据报发送到目标地址。这就好比写信,你不需要事先通知对方就可以直接把信寄出去,对方收到信后也不会给你发送确认收到的消息。
  • 工作原理:UDP 通信中,发送方将数据封装成 UDP 数据包,每个数据包包含源端口号、目的端口号、数据长度和数据等信息。然后,这些数据包通过网络传输到接收方。接收方根据目的端口号来接收和处理数据。由于 UDP 没有建立连接的过程,也没有确认机制,所以它不保证数据一定能准确无误地到达接收方,也不保证数据的接收顺序和发送顺序一致。
  • 特点
    • 简单高效:因为不需要建立和维护连接,所以 UDP 的开销小,传输速度快,适合对实时性要求高的应用,如视频直播、音频通话等。在这些应用中,偶尔丢失一些数据对整体的观看或收听体验影响不大,但如果因为建立连接等操作导致延迟过高,就会严重影响用户体验。
    • 无连接性:发送方可以随时向接收方发送数据,不受连接状态的限制,比较灵活。
    • 不可靠性:UDP 不提供数据的可靠性传输,可能会出现数据丢失、重复或乱序的情况。例如,在网络拥塞时,数据包可能会被丢弃。
  • 应用场景
    • 实时音视频传输:如视频会议、在线游戏等。在这些场景中,数据的实时性至关重要,少量的数据丢失可以接受,因为重新传输可能会导致更大的延迟,影响用户体验。
    • 域名系统(DNS):DNS 用于将域名转换为 IP 地址,通常使用 UDP 协议进行查询和响应。因为 DNS 查询通常比较简单,而且对速度要求较高,UDP 的快速传输特性能够满足其需求。
    • 简单网络管理协议(SNMP):用于管理和监控网络设备。SNMP 代理使用 UDP 将设备信息发送给管理站,由于对实时性有一定要求,且数据量通常不大,UDP 是合适的选择。

UDP和TCP通讯的区别

UDP 和 TCP 是两种常用的传输层协议,它们的设计目标和特性有显著差异,以下是具体对比:

1. 连接性

  • UDP(无连接)
    无需建立连接即可直接发送数据,类似 “写信”:
    发送方直接将数据包(数据报)发往接收方,不关心对方是否在线或能否接收
    典型场景:DNS 查询、视频直播。

  • TCP(面向连接)
    必须先建立连接(三次握手),类似 “打电话”:
    发送方和接收方需确认连接状态后才传输数据,确保通信双方就绪
    典型场景:网页浏览(HTTP)、文件传输(FTP)。

2. 可靠性

  • UDP(不可靠)

    • 不保证数据送达不重复不丢包按序到达
    • 若数据丢失或乱序,不重传不排序
      适用场景:对实时性要求高(如游戏、语音通话),少量丢包可接受。
  • TCP(可靠)

    • 通过确认机制(ACK)、重传机制(超时重传)、序列号保证数据完整且按序到达
    • 若数据丢失或乱序,自动重传并排序
      适用场景:对数据完整性要求高(如文件下载、银行交易)。

3. 传输效率与开销

  • UDP

    • 首部开销小(仅 8 字节),无连接建立和维护成本。
    • 传输速度快,适合小数据量、低延迟场景
  • TCP

    • 首部开销大(至少 20 字节),需维护连接状态(如序列号、确认号)。
    • 包含拥塞控制机制(避免网络拥堵),可能因重传导致延迟。
      :TCP 的可靠性是以牺牲速度和带宽为代价的。

4. 传输模式

  • UDP(数据报)

    • 数据以独立数据包传输,边界清晰(发送方发一个包,接收方收一个包)。
    • 示例:发送 “ABC” 和 “DEF”,接收方可能收到两个独立数据包。
  • TCP(字节流)

    • 数据以连续字节流传输,无边界概念(发送方分多次发送,接收方可能一次性读取)。
    • 示例:发送 “ABC” 和 “DEF”,接收方可能收到 “ABCDEF” 一个整体。

用Unity做客户端实现UDP同步通信逻辑

撰写C#脚本

using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

public class Lesson14 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 实现UDP客户端通信 收发字符串
        //1.创建套接字
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        //2.绑定本机地址
        IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);
        socket.Bind(ipPoint);
        //3.发送到指定目标
        IPEndPoint remoateIp = new IPEndPoint(IPAddress.Parse("127.0.0.1"),8081);
        //指定要发送的字节数和远程计算机的IP和端口
        socket.SendTo(Encoding.UTF8 .GetBytes ("我是客户端,你好"), remoateIp);
        //4.接收消息
        byte[] bytes = new byte[512];
        //这个变量主要是用来记录 谁发的消息给你 传入函数后 在内部 它会帮助我们进行赋值
        EndPoint remoateIp2 = new IPEndPoint(IPAddress.Any, 0);
        int length= socket.ReceiveFrom(bytes, ref remoateIp2);
        print("IP:"+(remoateIp2 as IPEndPoint).Address .ToString()
            +"Port:"+(remoateIp2 as IPEndPoint).Port 
            +"发来了:"+Encoding.UTF8.GetString(bytes, 0, length));
        //5.释放关闭
        socket.Shutdown(SocketShutdown.Both);
        socket.Close();
        #endregion 
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

用本地做服务器实现UDP同步通信逻辑

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace UDPServer
{
    class Program
    {
        static void Main(string[] args)
        {
            #region 实现UDP服务端通信收发字符串
            //1.创建套接字
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            //2.绑定本机地址
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8081);
            socket.Bind(ipPoint);
            Console.WriteLine("服务器开启成功");
            //3.接收消息
            byte[] bytes = new byte[512];
            EndPoint remoateIp2 = new IPEndPoint(IPAddress.Any, 0);
            int length = socket.ReceiveFrom(bytes, ref remoateIp2);
            Console .WriteLine("IP:" + (remoateIp2 as IPEndPoint).Address.ToString()
                + "Port:" + (remoateIp2 as IPEndPoint).Port
                + "发来了:" + Encoding.UTF8.GetString(bytes, 0, length));
            //4.发送到指定地址
            socket.SendTo(Encoding.UTF8.GetBytes("欢迎给服务器发消息"), remoateIp2);
            //5.释放关闭
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            #endregion 
            Console.ReadKey();
        }
    }
}

实现结果

将脚本挂载到Unity场景中,运行服务器,成功实现客户端与服务器UDP同步通信