C# 如何正确实现异步udp网络?

C# 如何正确实现异步udp网络?,c#,asynchronous,.net-4.0,udp,socketasynceventargs,C#,Asynchronous,.net 4.0,Udp,Socketasynceventargs,和其他许多人一样,我正在尝试创建一个网络库。要求基本上如下所示: 异步工作并为实时应用程序做好准备(我脑子里有FPS游戏) 使用UDP并根据需要在顶部设置精简协议层 本机使用IPv6 支持多种平台(请阅读:我想要单声道支持!) 现在,在阅读了一些关于如何做到这一点(最鼓舞人心的是)的书籍后,我设置了我的开发环境,思考了如何做到这一点,并提出了以下基本工作流程: 初始化套接字并告诉它使用“UDPv6” 将该套接字绑定到端口,并使异常不会困扰用户。有一个“绑定”属性告诉他套接字设置正确 了解本地

和其他许多人一样,我正在尝试创建一个网络库。要求基本上如下所示:

  • 异步工作并为实时应用程序做好准备(我脑子里有FPS游戏)
  • 使用UDP并根据需要在顶部设置精简协议层
  • 本机使用IPv6
  • 支持多种平台(请阅读:我想要单声道支持!)
现在,在阅读了一些关于如何做到这一点(最鼓舞人心的是)的书籍后,我设置了我的开发环境,思考了如何做到这一点,并提出了以下基本工作流程:

  • 初始化套接字并告诉它使用“UDPv6”
  • 将该套接字绑定到端口,并使异常不会困扰用户。有一个“绑定”属性告诉他套接字设置正确
  • 了解本地计算机支持上NIC的最大MTU
  • 初始化多个SocketAsyncEventArgs,告诉其完成的事件调用私有分派方法,并从步骤3将其缓冲区设置为最大MTU的大小
  • 使用第一个SAEA对象调用Sockets ReceiveFromAsync方法
  • 当收到数据时,我会执行以下操作:

  • 使用下一个可用SAEA对象调用ReceiveFromAsync方法
  • 从当前SAEA对象获取缓冲区和发送者信息,并使其再次可用
  • 使用收到的消息触发新事件
  • 我对这种方法做了一些测试,效果很好。我每10毫秒向它发送一条消息,200字节的数据持续10000个周期,CPU或内存负载几乎没有增加。只有NIC负载在增加。但是我提出了一些问题|问题:

    • 当我处理PeerSocket类(即保存套接字)时,我会处理每个SAEA对象。但由于其中至少有一个仍在侦听新消息,因此会抛出ObjectDisposedException。有没有办法让它停止倾听
    • MTU在到达其他对等点的路上可能会有所不同,每个SAEA对象的缓冲区是否应该使用不同的指示器来确定缓冲区的大小
    • 我还不知道如何处理零碎的数据报。我将继续将“可靠性头”写入我正在发送的数据报中,但如果数据报被拆分,我不知道这个头信息,对吗

    该库有望有一天对其他人有用,并且它的存储库是公开的。对于这个问题,可以找到当前提交的内容

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

    客户:

    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之间的区别,特别是验证数据到达所需目的地的方式(特殊概念等)。

    您的问题是什么?我所有的问题都是问题,我想这就清楚了。谢谢你的努力,但是我想使用UDP套接字和IPv6,它们与SocketAsyncEventArgs异步工作。我认为我对网络基础知识非常了解,这就是为什么这不是一个“如何将两台电脑相互连接”的问题;)