(运输层)UDP知识详解

来源:互联网 发布:linux建立文件 编辑:程序博客网 时间:2024/06/05 12:39

一、UDP简介

        UDP是传输层协议,和TCP协议处于一个分层中,但是与TCP协议不同,UDP协议并不提供超时重传,出错重传等功能,也就是说其是不可靠的协议。

        UDP协议是英文UserDatagramProtocol的缩写,即用户数据报协议,主要用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的C/S模式的网络应用都需要使用UDP协议。UDP协议直接位于IP(网际协议)协议的顶层。

        特点:

                  1)无连接,发送数据之前不需要建立连接。开销和发送之前的时间延迟较短。 

                  2)尽最大努力交付。(可以采取一定策略实现可靠传输)

                  3)面向报文,UDP对应用程序交付的报文,添加UDP首部后直接交给IP层。不合并,不拆分。

                  4)没有拥塞控制,网络拥塞不会使源主机发送率降低。

                  5)UDP支持一对一,一对多,多对一的交互通信

                  6)UDP首部开销较小,8字节(TCP为20字节、IP为20字节)

二,UDP首部格式

         源端口:2字节 =   16bit =0 ~ 65535

         目的端口:2字节

         长度:2字节  用户数据包的长度(最短为8字节,仅有头部)

         检验和:2字节

三,常见问题

         1,如果接受方UDP发现收到报文中目的端口不正确(不存在对应端口的应用程序)怎么办?

               丢弃该报文,由ICMP发送“端口不可达”差错报文给发送发。

               traceroute 工作原理,一种利用ICMP的TTL,另一种利用UDP的端口


四,程序实例

        Windows  C++ 源码  (开发环境:VS2005 ,Win7)

1)发送端

[html] view plaincopy
  1. #include <winsock2.h>  
  2. #include <iostream>  
  3. #pragma comment(lib, "ws2_32.lib")  
  4.   
  5. using namespace std;  
  6.   
  7. int main()  
  8. {  
  9.     SOCKET sock;                   //socket  
  10.     char szMsg[] = "this is a UDP test package";//被发送的字段  
  11.       
  12.     /*typedef unsigned short  WORD*/  
  13.     WORD wVersionRequested;//1.启动SOCKET库,版本为2.0  
  14.     WSADATA wsaData;//这个结构被用来存储 被WSAStartup函数调用后返回的 Windows Sockets数据  
  15.     int err;      
  16.     wVersionRequested = MAKEWORD( 2, 0 );//创建一个被指定变量连接而成的WORD变量。返回一个WORD变量    
  17.     err = WSAStartup(wVersionRequested, &wsaData );//Winsock服务的初始化  
  18.     if ( err != 0 )   
  19.     {  
  20.         cout<<"Socket2.0初始化失败,Exit!";  
  21.           
  22.     }     
  23.     if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 ) //判断是否是 2.0版本的socket  
  24.     {  
  25.         WSACleanup( );  
  26.           
  27.     }  
  28.       
  29.     //2.创建socket  
  30.     sock = socket(     
  31.         AF_INET,           //代表TCP/IP协议族: UDP, TCP, etc  
  32.         SOCK_DGRAM,        //SOCK_DGRAM说明是UDP类型,SOCK_STREAM是TCP类型  
  33.         0                  //protocol  
  34.         );  
  35.       
  36.     if (sock == INVALID_SOCKET ) {  
  37.         cout<<"Socket 创建失败,Exit!";  
  38.           
  39.     }  
  40.       
  41.     //3.设置发往的地址  
  42.     sockaddr_in addrto;            //发往的地址    
  43.     memset(&addrto,0,sizeof(addrto));  
  44.     addrto.sin_family=AF_INET;  
  45.     //以127开头的ip,并且客户和服务器在同一个局域网,服务方都可以接收(相当于广播);  
  46.     //指定服务方ip的可以接收  
  47.     addrto.sin_addr.s_addr=inet_addr("127.0.0.1");  
  48.       
  49.     addrto.sin_port=htons(7861);//端口号必须和服务器绑定的端口号一致  
  50.       
  51.     int nlen=sizeof(addrto);  
  52.     unsigned int uIndex = 1;  
  53.     while(true)  
  54.     {  
  55.         Sleep(1000);  
  56.         //从广播地址发送消息  
  57.         if( sendto(sock,szMsg,strlen(szMsg),0,(sockaddr*)&addrto,nlen)== SOCKET_ERROR )  
  58.             cout<<WSAGetLastError()<<endl;  
  59.         else  
  60.             cout<<uIndex++<<":an UDP package is sended."<<endl;  
  61.     }  
  62.       
  63.     if (!closesocket(sock))   
  64.     {  
  65.         WSAGetLastError();  
  66.           
  67.     }  
  68.     if (!WSACleanup())   
  69.     {  
  70.         WSAGetLastError();  
  71.           
  72.     }     
  73. }  


2)接收端

[html] view plaincopy
  1. #include <winsock2.h>  
  2. #include <iostream>  
  3. #pragma comment(lib, "ws2_32.lib")  
  4.   
  5. using namespace std;  
  6. void main(void)  
  7. {  
  8.     SOCKET sock;  
  9.       
  10.     //1.启动SOCKET库,版本为2.0  
  11.     WORD wVersionRequested;  
  12.     WSADATA wsaData;  
  13.     int err;      
  14.     wVersionRequested = MAKEWORD( 2, 0 );     
  15.     err = WSAStartup( wVersionRequested, &wsaData );  
  16.     if ( err != 0 )   
  17.     {  
  18.         cout<<"Socket2.0初始化失败,Exit!";  
  19.         return;  
  20.     }     
  21.     if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 )   
  22.     {  
  23.         WSACleanup();  
  24.         return;   
  25.     }  
  26.   
  27.     //2.创建套接字  
  28.     sock = socket(AF_INET,SOCK_DGRAM,0);  
  29.     if (sock == INVALID_SOCKET )  
  30.     {  
  31.         cout<<"Socket 创建失败,Exit!";  
  32.         return;  
  33.     }  
  34.   
  35.     //3.绑定  
  36.     sockaddr_in myaddr; //sockaddr_in相当于sockaddr结构  
  37.     memset(&myaddr,0,sizeof(myaddr));  
  38.     myaddr.sin_family=AF_INET;  
  39.     //如果绑定地址不是本机地址或者ADDR_ANY,则recvfrom函数不会正确接收,而是立刻返回  
  40.     myaddr.sin_addr.s_addr = inet_addr("127.0.0.1");  
  41.     //端口号必须和客户发往的端口号一致  
  42.     myaddr.sin_port=htons(7861);  
  43.     bind(sock,(sockaddr*)&myaddr,sizeof(myaddr));  
  44.       
  45.     int fromlength = sizeof(SOCKADDR);  
  46.     char buf[256]="";     
  47.     long number=0;  
  48.     while(1)  
  49.     {  
  50.           
  51.         if(recv(sock,buf,sizeof(buf),0))  
  52.         {  
  53.             cout<<number<<":"<<buf<<endl;  
  54.             number++;  
  55.         }  
  56.         memset(buf,0,sizeof(buf));  
  57.     }  
  58.   
  59.     if (!closesocket(sock))   
  60.     {  
  61.         WSAGetLastError();  
  62.         return;  
  63.     }  
  64.     if (!WSACleanup())  
  65.     {  
  66.         WSAGetLastError();  
  67.         return;  
  68.     }  
  69. }  
0 0