C#UDP通讯UdpClient

来源:互联网 发布:java工厂模式概念 编辑:程序博客网 时间:2024/05/23 01:43

目录(?)[+]

  1. 遇到如下两个问题
    1. 远程主机强迫关闭了一个现有的连接的错误
 
[html] view plain copy
print?
  1. class UdpClientClass  
  2. {  
  3.     /// <summary>  
  4.     /// 构建客户端  
  5.     /// </summary>  
  6.     /// <param name="servierIpAddress">服务器iP地址或者域名</param>  
  7.     /// <param name="sevierPort">服务器监听端口</param>  
  8.     /// <param name="locadPort">本地监听端口</param>  
  9.     /// <param name="timeOut">超时等待时间</param>  
  10.     public UdpClientClass(string servierIpAddress, int sevierPort, int locadPort, int timeOut)  
  11.     {  
  12.         if (FpHelper.CheckIpAddress(ref servierIpAddress) == true)  
  13.         {  
  14.             try  
  15.             {  
  16.                 ServerIPE = new IPEndPoint(IPAddress.Parse(servierIpAddress), sevierPort);  
  17.                 UdpListenClient = new UdpClient(locadPort);//固定通信端口  
  18.                 UdpListenClient.Client.ReceiveTimeout = 3000;  
  19.                 const long IOC_IN = 0x80000000;  
  20.                 const long IOC_VENDOR = 0x18000000;  
  21.                 const long SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;  
  22.   
  23.                 byte[] optionInValue = { Convert.ToByte(false) };  
  24.                 byte[] optionOutValue = new byte[4];  
  25.   
  26.                 UdpListenClient.Client.IOControl((IOControlCode)SIO_UDP_CONNRESET, optionInValue, optionOutValue);  
  27.   
  28.                  
  29.             }  
  30.             catch (System.Exception ex)  
  31.             {  
  32.                 MessageBox.Show("绑定端口失败" + ex.Message.ToString());  
  33.             }  
  34.   
  35.         }  
  36.     }  
  37.   
  38.     /// <summary>  
  39.     /// UDP发送类,绑定了一个固定的端口  
  40.     /// </summary>  
  41.     private static UdpClient UdpListenClient;  
  42.   
  43.     public event EventHandler MessageChanged;  
  44.   
  45.     /// <summary>  
  46.     /// 接收到服务器消息改变后触发的事件  
  47.     /// </summary>  
  48.     /// <param name="user"></param>  
  49.     public void OnMessageChanged(UdpClientClass fp)  
  50.     {  
  51.         if (MessageChanged != null)  
  52.         {  
  53.             MessageChanged(fp, null);  
  54.         }  
  55.     }  
  56.   
  57.     /// <summary>  
  58.     /// 服务器端的IP与端口  
  59.     /// </summary>  
  60.     private IPEndPoint ServerIPE = null;  
  61.   
  62.     bool IsReceiving = false;  
  63.   
  64.     public void Send(byte[] data, int len)  
  65.     {  
  66.       int len1 =  UdpListenClient.Send(data, len, ServerIPE);  
  67.         if (!IsReceiving)  
  68.             StartAndLsn();  
  69.     }  
  70.   
  71.     private Thread ClientRecThread;  
  72.   
  73.     private void StartAndLsn()  
  74.     {  
  75.         IsReceiving = true;  
  76.         ClientRecThread = new Thread(new ThreadStart(RecF));//启动新线程做接收  
  77.         ClientRecThread.IsBackground = true;  
  78.         ClientRecThread.Start();  
  79.   
  80.     }//启动并且 监听 服务器发来的数据  
  81.   
  82.   
  83.     private void RecF()//接收数据做服务  
  84.     {  
  85.         byte[] btRec = null;  
  86.         while (IsReceiving)  
  87.         {  
  88.             IPEndPoint remoteIPE = new IPEndPoint(IPAddress.Any, 0);  
  89.             btRec = UdpListenClient.Receive(ref remoteIPE);//UDP接收数据  
  90.             if (btRec.Length > 0 && remoteIPE.Address == ServerIPE.Address)//只处理特定的服务端的数据  
  91.             {  
  92.                 System.Windows.Forms.MessageBox.Show("res");  
  93.             }  
  94.             else  
  95.             {  
  96.             }  
  97.   
  98.         }  
  99.     }//循环接收数据  
  100. }  

遇到如下两个问题

[html] view plain copy
print?
  1. 1.UdpListenClient.Receive接受数据位阻塞模式,一直等待对方的返回,网上询问这个问题的很多,解答的却很多答非所问,仔细查看了UdpClient 类发现里面有一个Socket熟悉,  
[html] view plain copy
print?
  1. 关于通讯的底层问题都通过该熟悉来设置,该熟悉又设置发送或者接受超时的设置,如  
[html] view plain copy
print?
  1. UdpListenClient.Client.ReceiveTimeout = 3000;//设置超时接收返回  
[html] view plain copy
print?
  1. 2.udp通讯发现有时会产生<h2><a name="t1"></a><a class="singleposttitle" id="ctl01_TitleUrl" href="http://www.cnblogs.com/zhuangxuqiang/archive/2009/04/17/1437926.html">远程主机强迫关闭了一个现有的连接</a>的错误</h2><p>网上查找了很多,终于看到一篇</p><div id="cnblogs_post_body"><p>在公司一项目的UDP消息服务开发中时不时的会遇到这样一个问题:在UDP通信过程中,如果客户端中途断开,服务器会收到一个SocketException,错误ID为10054,描述是“远程主机强迫关闭了一个现有的连接”,紧接着的事就可怕了,UDP服务终止监听,所有客户端都受到了影响。也就是说一个客户端引起的异常导致了整个系统的崩溃。这个问题可是太严重了。</p><p>地球人都知道,UDP是无连接的,怎么会出现这个异常呢?百度了一圈,发现有这个问题的现象还不少,可就是没有一个有效的回复。再GOOGLE一圈,有点眉目了。找到了一个微软的解释和一个DOTNET的解决方法:</p><p>微软的解释:<a href="http://support.microsoft.com/kb/263823"><span style="color:#0000ff;">http://support.microsoft.com/kb/263823</span></a></p><p>DOTNET的处理方法:<a href="http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx"><span style="color:#0000ff;">http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx</span></a></p><p>不过处理方法似乎对参数的设置不太正确:  
  2. byte[] optionInValue = { Convert.ToByte(true) };  
  3. byte[] optionOutValue;</p><p>按照这样设置还是会抛出该异常。  
  4. 首先,根据微软的解释,optionInValue 传入的应该是false,而不是true;  
  5. 其次,根据微软的解释,optionOutValue应该是一个DWORD值,不应不赋值,或设为null。</p><p>根据以上两点,将以上两句改为:  
  6. byte[] optionInValue = { Convert.ToByte(false) };  
  7. byte[] optionOutValue = new byte[4];</p><p>经过<a title="软件测试知识库" class="replace_word" style="color:#df3434; font-weight:bold;" href="http://lib.csdn.net/base/softwaretest" target="_blank">测试</a>,模拟500个用户进行登录、收发消息、注销、异常退出、再连接,均没有再抛出该异常。服务表现稳定。</p></div><p> </p>  
   
0 0
原创粉丝点击