如何做异步udp网络权利

本文关键字:网络 udp 何做 异步 | 更新日期: 2023-09-27 18:28:10

与SO上的许多其他人一样,我正在尝试创建一个网络库。要求基本上是这样的:

  • 异步工作,为实时应用程序做好准备(我脑海中有FPS游戏)
  • 使用UDP,并根据需要在顶部设置一个精简协议层
  • 本机使用IPv6
  • 支持多个平台(阅读:我想要Mono支持!)

现在,在阅读了一些关于如何做到这一点的文章后(最鼓舞人心的是Gaffer在Games上的文章),我建立了我的开发环境,思考了如何实现这一点,并提出了以下基本工作流程:

  1. 初始化一个套接字并告诉它使用"UDPv6"
  2. 将该套接字绑定到一个端口,使异常不会困扰用户。有一个"绑定"属性,告诉他套接字设置正确
  3. 了解本地计算机上NIC支持的最大MTU
  4. 初始化多个SocketAsyncEventArgs,告诉其Completed事件调用私有调度方法,并将其缓冲区设置为步骤3中的最大MTU大小
  5. 调用带有第一个SAEA对象的Sockets ReceiveFromAsync方法

当数据进入时,我会执行以下操作:

  1. 使用下一个可用SAEA对象调用ReceiveFromAsync方法
  2. 从当前SAEA对象获取缓冲区和发件人信息,并使其再次可用
  3. 使用收到的消息启动一个新事件

我对这种方法做了一些测试,效果很好。我每10毫秒用200字节的数据向它发送一条消息,持续10000个周期,CPU或内存负载几乎没有增加。只有NIC负载在增加。然而,我遇到了一些问题:

  • 当我处理我的PeerSocket类(它持有套接字)时,我会处理每个SAEA对象。但由于其中至少有一个仍在侦听新消息,因此会抛出ObjectDisposedException。有没有办法让它停止听
  • MTU在通往其他对等体的途中可能会有所不同,也许每个SAEA对象的缓冲区应该使用不同的指示符来确定缓冲区大小
  • 我还不知道如何处理碎片数据报。我将继续将"可靠性标头"写入我正在发送的数据报中,但如果数据报被拆分,我不知道这个标头信息,对吧

该图书馆有望有一天对其他人有用,它的存储库是公开的。关于这个问题,当前提交可以在这里找到

如何做异步udp网络权利

哇,这真是一个巨大的主题。如果你以前没有学习过网络套接字,你最好学习一下。我可以给你要点,但绝对不够。

客户:

public void Get()
    {
        string data;
        string input;
        IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        try
        {
            socket.Connect(ipep);
        }
        catch (SocketException e)
        {
            Console.WriteLine("Unable to connect to server");
            Console.WriteLine(e.ToString());
            return;
        }
        NetworkStream ns = new NetworkStream(socket);
        StreamWriter sw = new StreamWriter(ns);
        StreamReader sr = new StreamReader(ns);
        data = sr.ReadLine();
        Console.WriteLine(data);
        while (true)
        {
            input = Console.ReadLine();
            if (input == "exite")
                break;
            sw.WriteLine(input);
            sw.Flush();
            data = sr.ReadLine();
            Console.WriteLine(data);
        }
        Console.WriteLine("Disconnected from server...");
        socket.Close();
        ns.Close();
        sr.Close();
        sr.Close();
    }

服务器:

public void Get()
    {
        string data;
        IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.Bind(ipep);
        socket.Listen(10);
        Console.WriteLine("Waiting for a client...");
        Socket client = socket.Accept();
        IPEndPoint newclient = (IPEndPoint)client.RemoteEndPoint;
        Console.WriteLine("Connected with: {0}, at Port: {1}", newclient.Address, newclient.Port);
        NetworkStream ns = new NetworkStream(client);
        StreamReader sr = new StreamReader(ns);
        StreamWriter sw = new StreamWriter(ns);
        string welcome = "Welcome to my test server";
        sw.Write(welcome);
        sw.Flush();
        while (true)
        {
            try
            {
                data = sr.ReadLine();
            }
            catch (IOException)
            {
                break;
            }
            Console.WriteLine(data);
            sw.WriteLine(data);
            sw.Flush();
        }
        Console.WriteLine("Disconnected from {0}", newclient.Address);
        sw.Close();
        ns.Close();
        sr.Close();
    }

请在控制台应用程序上试用,看看它是如何工作的。

基本上,服务器打开端口(在本例中为9050)等待客户端连接,然后客户端连接到服务器,然后开始通信。

你提到你必须使用UDP套接字,我想你知道UDP,但如果不知道,你最好检查TCP和UDP之间的区别,特别是验证数据到达所需目的地的方法(特别概念等等)。