C#UDP入门|Socket通信|UdpClient通信

  1 UDP 是User Datagram Protocol的简称, 中文名是用户数据包协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。它是IETF RFC 768是UDP的正式规范。      UDP报头
  2 
  3   UDP报头由4个域组成,其中每个域各占用2个字节,具体如下:
  4 
  5 
  6         源端口号
  7 
  8   目标端口号
  9 
 10   数据报长度
 11 
 12   校验值
 13 
 14   UDP协议使用端口号为不同的应用保留其各自的数据传输通道。UDP和TCP协议正是采用这一机制实现对同一时刻内多项应用同时发送和接收数据的支持。数据发送一方(可以是客户端或服务器端)将UDP数据报通过源端口发送出去,而数据接收一方则通过目标端口接收数据。有的网络应用只能使用预先为其预留或注册的静态端口;而另外一些网络应用则可以使用未被注册的动态端口。因为UDP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535。一般来说,大于49151的端口号都代表动态端口。
 15 
 16   数据报的长度是指包括报头和数据部分在内的总字节数。因为报头的长度是固定的,所以该域主要被用来计算可变长度的数据部分(又称为数据负载)。数据报的最大长度根据操作环境的不同而各异。从理论上说,包含报头在内的数据报的最大长度为65535字节。不过,一些实际应用往往会限制数据报的大小,有时会降低到8192字节。
 17 
 18   UDP协议使用报头中的校验值来保证数据的安全。校验值首先在数据发送方通过特殊的算法计算得出,在传递到接收方之后,还需要再重新计算。如果某个数据报在传输过程中被第三方篡改或者由于线路噪音等原因受到损坏,发送和接收方的校验计算值将不会相符,由此UDP协议可以检测是否出错。这与TCP协议是不同的,后者要求必须具有校验值。
 19 
 20 
 21   许多链路层协议都提供错误检查,包括流行的以太网协议,也许想知道为什么UDP也要提供检查和。其原因是链路层以下的协议在源端和终端之间的某些通道可能不提供错误检测。虽然UDP提供有错误检测,但检测到错误时,UDP不做错误校正,只是简单地把损坏的消息段扔掉,或者给应用程序提供警告信息。 
 22 
 23 UDP协议的几个特性
 24 
 25 
 26   (1) UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
 27 
 28   (2) 由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
 29 
 30   (3) UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
 31 
 32   (4) 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
 33 
 34   (5)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。
 35 
 36   (6)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。 
 37 
 38   虽然UDP是一个不可靠的协议,但它是分发信息的一个理想协议。例如,在屏幕上报告股票市场、在屏幕上显示航空信息等等。UDP也用在路由信息协议RIP(Routing Information Protocol)中修改路由表。在这些应用场合下,如果有一个消息丢失,在几秒之后另一个新的消息就会替换它。UDP广泛用在多媒体应用中,例如,Progressive Networks公司开发的RealAudio软件,它是在因特网上把预先录制的或者现场音乐实时传送给客户机的一种软件,该软件使用的RealAudio audio-on-demand protocol协议就是运行在UDP之上的协议,大多数因特网电话软件产品也都运行在UDP之上。
 39 
 40 1.我们先使用Socket的方法来实现
 41 
 42 服务器代码
 43 
 44 using System;
 45 using System.Collections.Generic;
 46 using System.Text;
 47 using System.Net;
 48 using System.Net.Sockets;
 49 namespace UDP
 50 {
 51    class Program
 52     {
 53         static void Main(string[] args)
 54         {
 55             int recv;
 56             byte[] data = new byte[1024]; 
 57 
 58             //得到本机IP,设置TCP端口号         
 59             IPEndPoint ip = new IPEndPoint(IPAddress.Any , 8001);
 60             Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram , ProtocolType.Udp);
 61             //绑定网络地址
 62             newsock.Bind(ip);
 63             Console.WriteLine("This is a Server, host name is {0}",Dns.GetHostName());
 64             //等待客户机连接
 65             Console.WriteLine("Waiting for a client");
 66             //得到客户机IP
 67             IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
 68             EndPoint Remote = (EndPoint)(sender);
 69             recv = newsock.ReceiveFrom(data, ref Remote);
 70             Console .WriteLine ("Message received from {0}: ", Remote.ToString ());
 71             Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv ));
 72             //客户机连接成功后,发送信息
 73             string welcome = "你好 ! ";
 74             //字符串与字节数组相互转换
 75             data  = Encoding .ASCII .GetBytes (welcome );
 76             //发送信息
 77             newsock .SendTo (data ,data.Length ,SocketFlags .None ,Remote );
 78             while (true )
 79             {
 80                 data =new byte [1024];
 81                 //发送接受信息
 82                 recv =newsock.ReceiveFrom(data ,ref Remote);
 83                 Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv));
 84                 newsock .SendTo (data ,recv ,SocketFlags .None ,Remote );
 85             }
 86         }
 87     }
 88 }
 89  
 90 
 91 客户端代码 :
 92 
 93 using System;
 94 using System.Collections.Generic;
 95 using System.Linq;
 96 using System.Text;
 97 using System.Net;
 98 using System.Net.Sockets;
 99 namespace UDPClient
100 {
101     class Program
102     {
103         static void Main(string[] args)
104         {
105             byte[] data = new byte[1024];
106             string input ,stringData;
107             //构建TCP 服务器
108             Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());
109             //设置服务IP,设置TCP端口号
110             IPEndPoint ip = new IPEndPoint(IPAddress .Parse ("127.0.0.1") , 8001);
111             //定义网络类型,数据连接类型和网络协议UDP
112             Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
113             string welcome = "你好! ";
114             data = Encoding.ASCII.GetBytes(welcome);
115             server.SendTo(data, data.Length, SocketFlags.None, ip);
116             IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
117             EndPoint Remote = (EndPoint)sender;
118             data = new byte[1024];
119             //对于不存在的IP地址,加入此行代码后,可以在指定时间内解除阻塞模式限制
120             int recv = server.ReceiveFrom(data, ref Remote);
121             Console.WriteLine("Message received from {0}: ", Remote.ToString());
122             Console.WriteLine(Encoding .ASCII .GetString (data,0,recv));
123             while (true)
124             {
125                 input = Console .ReadLine ();
126                 if (input =="exit")
127                     break ;
128                 server .SendTo (Encoding .ASCII .GetBytes (input ),Remote );
129                 data = new byte [1024];
130                 recv = server.ReceiveFrom(data, ref Remote);
131                 stringData = Encoding.ASCII.GetString(data, 0, recv);
132                 Console.WriteLine(stringData);
133             }
134             Console .WriteLine ("Stopping Client.");
135             server .Close ();            
136         }
137     }
138 }
139  
140  
141 
142 2.下面咱们再来使用UdpClient 来实现他们之间的通信服务器端代码
143 
144 using   System;   
145   using   System.Net;   
146   using   System.Net.Sockets;   
147   using   System.Text;   
148     
149   public   class   Custom   {   
150     
151         private   static   readonly   IPAddress   GroupAddress   =   IPAddress.Parse("IP地址");   
152         private   const   int   GroupPort   =   11000;   
153         private   static   void   StartListener()   {   
154         bool   done   =   false;   
155             
156           UdpClient   listener   =   new   UdpClient();   
157           IPEndPoint   groupEP   =   new   IPEndPoint(GroupAddress,GroupPort);   
158     
159           try   {   
160               listener.JoinMulticastGroup(GroupAddress);   
161               listener.Connect(groupEP);   
162                 
163               while   (!done)   {   
164                   Console.WriteLine("Waiting   for   broadcast");   
165                   byte[]   bytes   =   listener.Receive(   ref   groupEP);   
166     
167                   Console.WriteLine("Received   broadcast   from   {0}   :\n   {1}\n",   
168                       groupEP.ToString(),   
169                       Encoding.ASCII.GetString(bytes,0,bytes.Length));   
170               }   
171     
172               listener.Close();   
173                 
174           }   catch   (Exception   e)   {   
175               Console.WriteLine(e.ToString());   
176           }   
177             
178       }   
179     
180       public   static   int   Main(String[]   args)   {   
181           StartListener();   
182     
183           return   0;   
184       }   
185   }   
186  
187 
188 客户端代码:
189 
190 using   System;   
191   using   System.Net;   
192   using   System.Net.Sockets;   
193   using   System.Text;   
194     
195   public   class   Client   {   
196     
197         private   static   IPAddress   GroupAddress   =    IPAddress.Parse("IP地址");   
198         private   static   int   GroupPort   =   11000;   
199           
200       private   static   void   Send(   String   message)   {   
201           UdpClient   sender   =   new   UdpClient();   
202           IPEndPoint   groupEP   =   new   IPEndPoint(GroupAddress,GroupPort);   
203     
204           try   {   
205               Console.WriteLine("Sending   datagram   :   {0}",   message);   
206               byte[]   bytes   =   Encoding.ASCII.GetBytes(message);   
207     
208               sender.Send(bytes,   bytes.Length,   groupEP);   
209                 
210               sender.Close();   
211                 
212           }   catch   (Exception   e)   {   
213               Console.WriteLine(e.ToString());   
214           }   
215             
216       }   
217     
218       public   static   int   Main(String[]   args)   {   
219           Send(args[0]);   
220     
221           return   0;   
222       }   
223   }
224  
225 
226 如果您是采用窗体的形式建议使用这种格式,否则在接收数据时可能会出现死机的现象
227 // 创建一个子线程
228             Thread thread = new Thread(
229                 delegate()
230                 {
231                     try
232                     {
233                         //在这里写你的代码
234                     }
235                     catch (Exception )
236                     {
237                     }
238                 }
239             );
240             thread.Start();
241  

 

posted @ 2013-08-09 16:48  wilderhorse  阅读(1015)  评论(0编辑  收藏  举报