【传输层】UDP知识详解

一,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)发送端

#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main()
{
	SOCKET sock;                   //socket
	char szMsg[] = "this is a UDP test package";//被发送的字段
	
	/*typedef unsigned short  WORD*/
	WORD wVersionRequested;//1.启动SOCKET库,版本为2.0
	WSADATA wsaData;//这个结构被用来存储 被WSAStartup函数调用后返回的 Windows Sockets数据
	int err;	
	wVersionRequested = MAKEWORD( 2, 0 );//创建一个被指定变量连接而成的WORD变量。返回一个WORD变量	
	err = WSAStartup(wVersionRequested, &wsaData );//Winsock服务的初始化
	if ( err != 0 ) 
	{
		cout<<"Socket2.0初始化失败,Exit!";
		
	}	
	if ( LOBYTE( wsaData.wVersion ) != 2 ||	HIBYTE( wsaData.wVersion ) != 0 ) //判断是否是 2.0版本的socket
	{
		WSACleanup( );
		
	}
	
	//2.创建socket
	sock = socket(   
		AF_INET,           //代表TCP/IP协议族: UDP, TCP, etc
		SOCK_DGRAM,        //SOCK_DGRAM说明是UDP类型,SOCK_STREAM是TCP类型
		0                  //protocol
		);
	
	if (sock == INVALID_SOCKET ) {
		cout<<"Socket 创建失败,Exit!";
		
	}
	
	//3.设置发往的地址
	sockaddr_in addrto;            //发往的地址	
	memset(&addrto,0,sizeof(addrto));
	addrto.sin_family=AF_INET;
	//以127开头的ip,并且客户和服务器在同一个局域网,服务方都可以接收(相当于广播);
	//指定服务方ip的可以接收
    addrto.sin_addr.s_addr=inet_addr("127.0.0.1");
	
	addrto.sin_port=htons(7861);//端口号必须和服务器绑定的端口号一致
	
	int nlen=sizeof(addrto);
	unsigned int uIndex = 1;
	while(true)
	{
		Sleep(1000);
		//从广播地址发送消息
		if( sendto(sock,szMsg,strlen(szMsg),0,(sockaddr*)&addrto,nlen)== SOCKET_ERROR )
			cout<<WSAGetLastError()<<endl;
		else
			cout<<uIndex++<<":an UDP package is sended."<<endl;
	}
	
	if (!closesocket(sock)) 
	{
		WSAGetLastError();
		
	}
	if (!WSACleanup()) 
	{
		WSAGetLastError();
		
	}	
}


2)接收端

#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")

using namespace std;
void main(void)
{
	SOCKET sock;
	
	//1.启动SOCKET库,版本为2.0
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;	
	wVersionRequested = MAKEWORD( 2, 0 );	
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) 
	{
		cout<<"Socket2.0初始化失败,Exit!";
		return;
	}	
	if ( LOBYTE( wsaData.wVersion ) != 2 ||	HIBYTE( wsaData.wVersion ) != 0 ) 
	{
		WSACleanup();
		return; 
	}

	//2.创建套接字
	sock = socket(AF_INET,SOCK_DGRAM,0);
	if (sock == INVALID_SOCKET )
	{
		cout<<"Socket 创建失败,Exit!";
		return;
	}

	//3.绑定
	sockaddr_in myaddr; //sockaddr_in相当于sockaddr结构
	memset(&myaddr,0,sizeof(myaddr));
	myaddr.sin_family=AF_INET;
	//如果绑定地址不是本机地址或者ADDR_ANY,则recvfrom函数不会正确接收,而是立刻返回
 	myaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	//端口号必须和客户发往的端口号一致
	myaddr.sin_port=htons(7861);
 	bind(sock,(sockaddr*)&myaddr,sizeof(myaddr));
	
	int fromlength = sizeof(SOCKADDR);
	char buf[256]="";	
	long number=0;
	while(1)
	{
		
		if(recv(sock,buf,sizeof(buf),0))
		{
			cout<<number<<":"<<buf<<endl;
			number++;
		}
		memset(buf,0,sizeof(buf));
	}

	if (!closesocket(sock)) 
	{
		WSAGetLastError();
		return;
	}
	if (!WSACleanup())
	{
		WSAGetLastError();
		return;
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值