UDPClient类通信实践

本文详细介绍了如何使用UDPClient类构建一个UDP服务器端程序,强调了在使用过程中的注意事项,如避免同一主机上的Server和Client端口冲突,并探讨了非阻塞式接收的方法以及在发送数据时可能出现的异常处理,特别是当目标IP地址不存在时的SocketError.ConnectionReset异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、一个典型的使用UDPClient类实现的UDP服务器端程序,分析工作集成在代码内部

        private const int srcPort = 4100;


        static void Main(string[] args)

        {

          //使用Dns类中的GetHostAddresses方法可以得到本机上所有网卡的IP地址

            IPAddress[] ipArray = Dns.GetHostAddresses(System.Environment.MachineName);

            Console.Clear();
            int i = 0;
            for (i = 0; i < ipArray.Length; i++)
            {
                Console.WriteLine("   {0} {1}", i, ipArray[i].ToString());
            }
            Console.WriteLine("   {0} All", i);
            Console.WriteLine("-----------------------------------");
            Console.Write("Select NIC interface to bind: ");
            ConsoleKeyInfo cki = Console.ReadKey(false);
            int sel = (int)(cki.KeyChar - '0');
            if (sel < 0 || sel > i)
            {
                Console.WriteLine("");
                Console.WriteLine("Error selection!");
                return;
            }


           //选取一个IP地址做监听(绑定),也可以选取所有IP

            IPEndPoint iepHost = new IPEndPoint(IPAddress.Any, srcPort);
            if (i > sel) iepHost.Address = ipArray[sel];
            UdpClient uc = new UdpClient(iepHost);
            Console.WriteLine("");
            Console.WriteLine("Test Extra Server started!");


            IPEndPoint iepRemote = new IPEndPoint(IPAddress.Any, 0);
            while (!Console.KeyAvailable) {
                Thread.Sleep(100);

                try {

                    //利用Available属性可以使阻塞式IO当做不阻塞使用

                    if (uc.Available > 0) {
                        byte[] buf = uc.Receive(ref iepRemote);
                        if (buf.Length < 3) continue;
                        switch (buf[1]) {
                            case 1:
                                buf = new byte[1460];
                                respWho(buf, iepHost);
                                uc.Send(buf, 11, iepRemote);
                                break;
                            case 2:
                                buf = new byte[1460];
                                respUpload(buf, iepHost);
                                uc.Send(buf, 23, iepRemote);
                                break;
                            case 3:
                                buf = new byte[1460];
                                respDownload(buf, iepHost);
                                uc.Send(buf, 4, iepRemote);
                                break;
                        }
                    }

                }

               //注意在使用UDP类的属性和方法时会产生异常

                catch (SocketException se) {
                    if (se.SocketErrorCode != SocketError.ConnectionReset) throw se;
                }
                catch (Exception e) {
                    Console.WriteLine("{0}", e.ToString());
                }
            }

 二、UDPClient类的做Server/Client端要考虑的问题

如果Server/Client允许同时存在于一台主机中,要注意发送端口与接收端口不要使用同一个端口,否则Server监听端口与Client监听端口一样的话,第一、要用端口复用技术,使用(SOCKREUSED)的OPTION;第二、Client发送的报文可能Server端无法收到,而是被环回到Client接收。

三、UDPClient类非阻塞式接收用法

利用Available属性,该属性的值指示着接收缓冲区中的数据报字节数,在调用Receive接收时先查看该属性是否为0,如果不为0则表示接收缓冲区中可能有数据,但是出现异常时,该属性可能为1,这时要捕获异常进行处理

四、有时UDPClient在调用Send发送数据时,对方IP地址不存在,会产生异常(SocketError.ConnectionReset),我的判断是,对方IP地址不存在的时候,ARP解析无法完成,UDP包根本无法发送出去。所以产生异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值