一.UDP协议
UDP(User Datagram Protocol)协议就是“用户数据报协议”,它是一种无连接的协议,无连接主要是和TCP协议相比较的。我们知道当利用TCP协议传送数据的时候,首先必须建立连接(也就是所谓的握手)才可以传输数据。而当计算机利用UDP协议进行数据传输的时候,发送方只需要知道对方的IP地址和端口号就可以发送数据,而并不需要进行连接。
由于UDP协议并不需要进行确定的连接,所以编写基于UDP协议的应用程序比起编写基于TCP协议的应用程序要简单些(程序中可以不需要考虑连接和一些异常的捕获工作)。但同时也给基于UDP协议编写的程序带来了一个致命的缺点,UDP由于不提供可靠数据的传输,当计算机之间利用UDP协议传送数据的时候,发送方只管发送数据,而并不确认数据是否被对方接收。这样就会导致某些UDP协议数据包在传送的过程中丢失,尤其网络质量不令人满意的情况下,丢失数据包的现象会更严重。这就是为什么在网络上传输重要数据不采用UDP协议的原因。
可见UDP是一种不面向连接的网络协议,既有其优点,也有其不足,具体如下:
1.基于UDP协议的网络应用程序,实现起来比较简单,并且基于UDP协议的网络应用程序在运行时,由于受到环境影响较小,所以不容易出错。
2.UDP协议占用网络资源较少,数据处理较快,所以在网络中传送对安全性要求不是十分高数据时,其优点比较明显。所谓对安全性要求不高的数据,是指那些不重要的数据,或者是即使丢失若干数据,也不影响其整体的数据,如音频数据等。目前很多流行的网络应用程序都是基于UDP协议的,如OICQ、ICQ等。
3.由于其不是面向连接的网络协议,其缺点也是非常明显的,有些时候甚至是致命的。因为使用UDP协议来传送数据,在数据发送后,在发送方并不确认对方是否接收到。这样就可能导致传送的数据在网络中丢失,尤其在网络条件并不很好的情况下,丢失数据包的现象就更多。所以传送重要数据一般不采用UDP协议。
二.C#发送、接收UDP数据包使用的主要类及其用法
用Visual C#实现UDP协议,最为常用,也是最为关键的类就是UdpClient,UdpClient位于命名空间System.Net.Sockets中,Visual C#发送、接收UDP数据包都是通过UdpClient类的。
表-1 UdpClient类中常用方法及其说明
方法 |
说明 |
Close |
关闭 UDP 连接 |
Connect |
建立与远程主机的连接 |
DropMulticastGroup |
退出多路广播组 |
JoinMulticastGroup |
将 UdpClient 添加到多路广播组 |
Receive |
返回已由远程主机发送的 UDP 数据文报 |
Send |
将 UDP 数据文报发送到远程主机 |
表-2:UdpClient类中常用属性及其说明
属性 |
说明 |
Active |
获取或设置一个值,该值指示是否已建立了与远程主机的连接 |
Client |
获取或设置基础网络套接字 |
1. C#使用UdpClient类发送UDP数据包
在具体使用中,一般分成二种情况:
(1) 知道远程计算机IP地址:
Send方法的调用语法如下:
publicint Send ( byte[] dgram , int bytes , IPEndPoint endPoint ) ;
参数说明:
dgram 要发送的 UDP数据文报(以字节数组表示)。
bytes 数据文报中的字节数。
endPoint一个 IPEndPoint类型,它表示要将数据文报发送到的主机IP和端口。
返回值 已发送的字节数。
下面使用UdpClient发送UDP数据包的具体的调用例子:
IPAddressHostIP = new IPAddress.Parse ( "192.168.0.188" ) ; IPEndPointhost = new IPEndPoint ( HostIP , 10002 ) ; UdpClient.Send( "发送的字节" , "发送的字节长度" , host ) ;
(2) 知道远程计算机名称
Send方法的调用语法如下:
publicint Send ( byte[ ] dgram , int bytes , string hostname , int port ) ;
参数说明:
dgram 要发送的 UDP数据文报(以字节数组表示)。
bytes 数据文报中的字节数。
hostname要连接到的远程主机的名称。
port 要与其通讯的远程端口号。
返回值 已发送的字节数。
2. C#使用UdpClient类接收UDP数据包:
接收UDP数据包使用的是UdpClient中的Receive方法,此方法的调用语法如下:
publicbyte [] Receive ( ref IPEndPoint remoteEP ) ;
参数
remoteEP是一个 IPEndPoint类的实例,它表示网络中发送此数据包的节点。
下面使用UdpClient接收UDP数据包的具体的调用例子:
server= new UdpClient ( ) ; receivePoint= new IPEndPoint (new IPAddress(127001), 8080 ) ; byte[]recData = server.Receive ( ref receivePoint ) ;
三.UDP客户端代码,客户端程序主要就是向服务器端发送数据
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; namespace UDPClient { class UDPClient { private UdpClient client; private IPEndPoint receivePoint; //发送数据函数 public void start_client() { Console.WriteLine("客户端启动"); client = new UdpClient(8080);//客户端使用8080端口发送数据 receivePoint = new IPEndPoint(new IPAddress(127001), 10002); IPAddress HostIP; bool continueLoop = true; while(continueLoop){ System.Text.ASCIIEncoding encode = new System.Text.ASCIIEncoding(); string sendString = Console.ReadLine(); byte[] sendData = encode.GetBytes(sendString); try { HostIP = IPAddress.Parse("127.0.0.1"); IPEndPoint host = new IPEndPoint(HostIP, 10002); //服务器端套接字,客户端发送数据到此套接字 client.Send(sendData, sendData.Length, host); byte[] recData = client.Receive(ref receivePoint);//客户端使用8080端口,接收服务器从10002端口发送过来的数据 Console.WriteLine(encode.GetString(recData)); continueLoop = false; }catch{ client.Close(); return; } } } } class Program { static void Main(string[] args) { UDPClient udpClient = new UDPClient(); udpClient.start_client(); } } }
四.UDP服务器端代码,服务器端程序主要就是接收客户端发送的数据
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; namespace UdpServer { class UdpServer { private UdpClient server; private IPEndPoint receivePoint; private Thread startServer; //接受数据函数start_server public void start_server() { Console.WriteLine("UDPServer启动。。。"); while (true) { ASCIIEncoding encode = new ASCIIEncoding(); byte[] recData = server.Receive(ref receivePoint);//服务器端从10002端口接收receivePoint发送来的数据包 string Read_str = encode.GetString(recData); Console.WriteLine(Read_str); byte[] sendData = encode.GetBytes("OK"); server.Send(sendData, sendData.Length, receivePoint);//服务器将数据发送到客户端的8080端口 } } //创建一个线程 public void run() { //利用本地端口号初始化一个UDP网络服务 server = new UdpClient(10002);//本地端口号,客户端将数据发送到服务器的10002端口,服务器从10002端口接收数据 receivePoint = new IPEndPoint(new IPAddress(127001),8080); //客户端的套接字 startServer = new Thread(new ThreadStart(start_server)); //启动线程 startServer.Start(); } } class Program { static void Main(string[] args) { UdpServer udpServer = new UdpServer(); udpServer.run(); } } }