您的位置:

c#udp协议详解

一、UDP协议概述

UDP(User Datagram Protocol,用户数据报协议)是一种无连接的协议,数据报文的大小在IP协议层被限制为65,507字节。UDP不保证数据的可靠传输,没有重传机制,而且无序且不重复,比TCP更加轻量级,通常用于实时的应用场景,如游戏,视频等。

二、c#udp实现

1、发送数据

c#中使用UdpClient实现UDP协议的发送数据,示例代码如下:

using System.Net.Sockets;
using System.Text;

class SendData
{
    static void Main(string[] args)
    {
        //定义IP和端口
        string ip = "127.0.0.1";
        int port = 8888;
        //定义发送的数据
        string message = "Hello World!";
        byte[] sendBytes = Encoding.ASCII.GetBytes(message);
        
        //定义UDP客户端
        UdpClient client = new UdpClient();
        //发送数据
        client.Send(sendBytes, sendBytes.Length, ip, port);
        //关闭UDP客户端
        client.Close();
    }
}

2、接收数据

c#中使用UdpClient实现UDP协议的接收数据,示例代码如下:

using System.Net;
using System.Net.Sockets;
using System.Text;

class ReceiveData
{
    static void Main(string[] args)
    {
        //定义IP和端口
        string ip = "127.0.0.1";
        int port = 8888;
        //定义UDP客户端
        UdpClient client = new UdpClient(port);
        //定义接收数据的IP和端口
        IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Parse(ip), port);

        while (true)
        {
            //接收数据
            byte[] receiveBytes = client.Receive(ref remoteIpep);
            string message = Encoding.ASCII.GetString(receiveBytes, 0, receiveBytes.Length);
            Console.WriteLine("接收到的数据为:" + message);
        }
        
        //关闭UDP客户端
        client.Close();
    }
}

三、小标题

1、c#udp实现视频传输

UDP适用于实时的应用,如实时视频传输。c#可以结合FFmpeg库实现视频的采集和传输,示例代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FFmpeg.AutoGen;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace UdpVideoStreaming
{
    class Program
    {
        static void Main(string[] args)
        {
            int videoStreamIndex = -1;

            //初始化FFmpeg
            ffmpeg.av_register_all();
            ffmpeg.avcodec_register_all();
            ffmpeg.avformat_network_init();

            //打开视频
            AVFormatContext* pFormatContext = null;
            if (ffmpeg.avformat_open_input(&pFormatContext, "test.mp4", null, null) != 0)
            {
                Console.WriteLine("无法打开视频文件");
                return;
            }

            //查找视频流
            if (ffmpeg.avformat_find_stream_info(pFormatContext, null) < 0)
            {
                Console.WriteLine("无法查找视频流");
                return;
            }

            Codecs.CodecContext videoCodecContext = new Codecs.CodecContext();
            videoStreamIndex = ffmpeg.av_find_best_stream(pFormatContext, AVMediaType.AVMEDIA_TYPE_VIDEO, -1, -1,videoCodecContext.Codec, 0);
            if (videoStreamIndex == -1)
            {
                Console.WriteLine("无法找到视频流");
                return;
            }

            //打开视频解码器
            if (ffmpeg.avcodec_open2(videoCodecContext, videoCodecContext.Codec, null) < 0)
            {
                Console.WriteLine("无法打开视频解码器");
                return;
            }

            //定义接收数据的IP和端口
            IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);

            //定义发送数据的UDP客户端
            UdpClient client = new UdpClient();

            AVPacket* pPacket = ffmpeg.av_packet_alloc();
            while (ffmpeg.av_read_frame(pFormatContext, pPacket) >= 0)
            {
                if (pPacket->stream_index == videoStreamIndex)
                {
                    //发送视频数据
                    int length = 0;
                    byte[] data = new byte[pPacket->size];
                    Marshal.Copy(new IntPtr(pPacket->data), data, 0, pPacket->size);

                    client.Send(data, data.Length, remoteIpep);

                    //延时
                    Thread.Sleep(40);
                }

                ffmpeg.av_packet_unref(pPacket);
            }

            ffmpeg.av_packet_free(&pPacket);

            ffmpeg.avcodec_close(videoCodecContext);
            ffmpeg.avformat_close_input(&pFormatContext);
        }
    }
}

2、c#udp实现多人游戏

UDP适用于实时的应用,如多人网络游戏。c#可以使用Unity引擎结合UDP协议实现多人游戏,示例代码如下:

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System.Threading;

public class UdpController : MonoBehaviour
{
    private UdpClient udpClient;
    private Thread receiveThread;

    private void Start()
    {
        //定义接收数据的IP和端口
        IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 8888);
        //定义UDP客户端
        udpClient = new UdpClient(remoteIpep);
        //开启接收数据的线程
        receiveThread = new Thread(new ThreadStart(ReceiveData));
        receiveThread.Start();
    }

    private void OnApplicationQuit()
    {
        receiveThread.Abort();
        udpClient.Close();
    }

    private void ReceiveData()
    {
        while (true)
        {
            byte[] receiveBytes = udpClient.Receive(ref remoteIpep);
            string message = Encoding.ASCII.GetString(receiveBytes, 0, receiveBytes.Length);
            Debug.Log("接收到的数据为:" + message);
        }
    }

    private void SendData()
    {
        //定义发送的数据
        string message = "Hello World!";
        byte[] sendBytes = Encoding.ASCII.GetBytes(message);
        //定义发送的IP和端口
        IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
        //发送数据
        udpClient.Send(sendBytes, sendBytes.Length, remoteIpep);
    }
}

3、c#udp与TCP的区别

TCP为面向连接的协议,具有可靠性高的特点,可以保证数据的可靠传输。而UDP为无连接的协议,不保证数据的可靠传输,但是更轻量级。在网络游戏,实时视频传输等实时应用场景中,使用UDP能够保证更好的实时性。