tcp协议与 udp协议的区别Word格式.docx
《tcp协议与 udp协议的区别Word格式.docx》由会员分享,可在线阅读,更多相关《tcp协议与 udp协议的区别Word格式.docx(29页珍藏版)》请在冰豆网上搜索。
5、空分复用
6、统计复用
7、极化波复用
关于“信道复用技术”更深层次的问题,需要你自己去研究!
上面我们提到了“信道复用技术”!
知道了这一点,我们就很容易明白“物理信道”上的“虚拟信道”概念了!
不同的信道复用技术,使用不同的复用技术,目的就是创建“虚拟信道”。
一个TCP协议连接其实就是在物理线路上创建的一条“虚拟信道”。
这条“虚拟信道”建立后,在TCP协议发出FIN包之前(两个终端都会向对方发送一个FIN包),是不会释放的。
正因为这一点,TCP协议被称为面向连接的协议!
UDP协议,一样会在物理线路上创建一条“虚拟信道”,否则UDP协议无法传输数据!
但是,当UDP协议传完数据后,这条“虚拟信道”就被立即注销了!
因此,称UDP是不面向连接的协议!
大家要知道,一种物理线路,单位时间内,能够创建的“虚拟信道”是有限的!
从这个问题,大家应该明白了TCP协议和UDP协议为什么会共存了吧,然而,这只是其中一个原因而已!
那为什么又说TCP协议可靠,UDP协议不可靠呢?
以上说的是一个原因,还有一个原因是:
使用TCP协议传输数据,当数据从A端传到B端后,B端会发送一个确认包(ACK包)给A端,告知A端数据我已收到!
UDP协议就没有这种确认机制!
这一点,在做TCP协议首部分析时,会详加解释!
QQ普通会员就是使用的UDP协议进行传输数据!
既然UDP协议自身没有确认机制,这个工作可以交给应用层的进程来完成(QQ)!
大家使用QQ的时候,感觉出错的几率还是非常小吧!
当然,把这个确认工作完全交给QQ自身来做,就直接导致了,QQ软件体积增大!
有些应用,对数据传输可靠性要求非常高,例如大家浏览网页,通过网页注册帐号、转帐等服务,这是不容许出错的,使用TCP协议能把出错的可能性降到最低(当然,网络自身很糟糕,TCP协议也没办法)。
但是,提供这种可靠服务,会加大网络带宽的开销,因为“虚拟信道”是持续存在的,同时网络中还会出现大量的ACK和FIN包!
因此,鱼和熊掌不可兼得,需根据实际情况选择传输协议
TCP协议提供了可靠的数据传输,但是其拥塞控制、数据校验、重传机制的网络开销很大,不适合实时通信,所以选择开销很小的UDP协议来传输数据。
UDP协议是无连接的数据传输协议并且无重传机制,会发生丢包、收到重复包、乱序等情况。
而对于数据精确性要求不高的状态数据以及视频数据,丢包的影响不大。
因为会不断收到新的包,丢失的个别包会有新的包来覆盖,所以只需在远程控制系统的通信部分自行处理乱序及重复包的问题,而对于丢包的问题一般不作处理。
但对于命令包这种需要精确收发的数据,可在程序的开发中加入丢包重发和超时丢弃的处理。
当然,如果开发的是对于实时性要求不高的事件型控制命令的传输,不希望发生指令的丢失也可以直接采用TCP协议。
TCP的重传机制正好适合这种情况。
非面向连接的传输协议在数据传输之前不建立连接,而是在每个中间节点对非面向连接的包和数据包进行路由。
没有点到点的连接,非面向连接的协议,如UDP,是不可靠的连接。
当一个UDP数据包在网络中移动时,发送过程并不知道它是否到达了目的地,除非应用层已经确认了它已到达的事实。
非面向连接的协议也不能探测重复的和乱序的包。
标准的专业术语用“不可靠”来描述UDP。
在现代网络中,UDP并不易于导致传输失败,但是你也不能肯定地说它是可靠的。
UDP
UserDatagramProtocol
用户数据报协议
UDP是ISO参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
UDP协议基本上是IP协议与上层协议的接口。
UDP协议适用端口分辨运行在同一台设备上的多个应用程序。
∙1简介
∙2为什么要使用UDP?
∙3UDP报头
∙4UDP协议的几个特性
∙5UDPvsTCP
∙6UDP协议的应用
∙7UDP程序设计
UDP-简介
UDP协议的全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包。
在OSI模型中,在第四层——传输层,处于IP协议的上一层。
UDP有不提供数据报分组、组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
UDP用来支持那些需要在计算机之间传输数据的网络应用。
包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。
UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天,UDP仍然不失为一项非常实用和可行的网络传输层协议。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。
根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。
UDP协议的主要作用是将网络数据流量压缩成数据报的形式。
一个典型的数据报就是一个二进制数据的传输单位。
每一个数据报的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
UDP-为什么要使用UDP?
在选择使用协议的时候,选择UDP必须要谨慎。
在网络质量令人不十分满意的环境下,UDP协议数据包丢失会比较严重。
但是由于UDP的特性:
它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
比如我们聊天用的ICQ和OICQ就是使用的UDP协议。
UDP-UDP报头
UDP报头由4个域组成,其中每个域各占用2个字节,具体如下:
源端口号
目标端口号
数据报长度
校验值
UDP协议使用端口号为不同的应用保留其各自的数据传输通道。
UDP和TCP协议正是采用这一机制实现对同一时刻内多项应用同时发送和接收数据的支持。
数据发送一方(可以是客户端或服务器端)将UDP数据报通过源端口发送出去,而数据接收一方则通过目标端口接收数据。
有的网络应用只能使用预先为其预留或注册的静态端口;
而另外一些网络应用则可以使用未被注册的动态端口。
因为UDP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535。
一般来说,大于49151的端口号都代表动态端口。
数据报的长度是指包括报头和数据部分在内的总字节数。
因为报头的长度是固定的,所以该域主要被用来计算可变长度的数据部分(又称为数据负载)。
数据报的最大长度根据操作环境的不同而各异。
从理论上说,包含报头在内的数据报的最大长度为65535字节。
不过,一些实际应用往往会限制数据报的大小,有时会降低到8192字节。
UDP协议使用报头中的校验值来保证数据的安全。
校验值首先在数据发送方通过特殊的算法计算得出,在传递到接收方之后,还需要再重新计算。
如果某个数据报在传输过程中被第三方篡改或者由于线路噪音等原因受到损坏,发送和接收方的校验计算值将不会相符,由此UDP协议可以检测是否出错。
这与TCP协议是不同的,后者要求必须具有校验值。
检查和的详细计算可在RFC1071中找到,现举一例说明使用检查和检测错误的道理。
例如,假设从源端A要发送下列3个16位的二进制数:
word1,word2和word3到终端B,检查和计算如下:
word1
0110011001100110
word1
010*********
0000111100001111
sum=word1+word2+word3
1100101011001010
检查和(sum的反码)
0011010100110101
从发送端发出的4个(word1,2,3以及检查和)16位二进制数之和为1111111111111111,如果接收端收到的这4个16位二进制数之和也是全“1”,就认为传输过程中没有出差错。
许多链路层协议都提供错误检查,包括流行的以太网协议,也许想知道为什么UDP也要提供检查和。
其原因是链路层以下的协议在源端和终端之间的某些通道可能不提供错误检测。
虽然UDP提供有错误检测,但检测到错误时,UDP不做错误校正,只是简单地把损坏的消息段扔掉,或者给应用程序提供警告信息。
UDP-UDP协议的几个特性
(1)UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。
在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;
在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
(2)由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
(3)UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
(4)吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
虽然UDP是一个不可靠的协议,但它是分发信息的一个理想协议。
例如,在屏幕上报告股票市场、在屏幕上显示航空信息等等。
UDP也用在路由信息协议RIP(RoutingInformationProtocol)中修改路由表。
在这些应用场合下,如果有一个消息丢失,在几秒之后另一个新的消息就会替换它。
UDP广泛用在多媒体应用中,例如,ProgressiveNetworks公司开发的RealAudio软件,它是在因特网上把预先录制的或者现场音乐实时传送给客户机的一种软件,该软件使用的RealAudioaudio-on-demandprotocol协议就是运行在UDP之上的协议,大多数因特网电话软件产品也都运行在UDP之上。
UDP-UDPvsTCP
UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同。
TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;
发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。
与TCP不同,UDP协议并不提供数据传送的保证机制。
如果在从发送方到接收方的传递过程中出现数据报的丢失,协议本身并不能做出任何检测或提示。
因此,通常人们把UDP协议称为不可靠的传输协议。
相对于TCP协议,UDP协议的另外一个不同之处在于如何接收突法性的多个数据报。
不同于TCP,UDP并不能确保数据的发送和接收顺序。
例如,一个位于客户端的应用程序向服务器发出了以下4个数据报
D1
D22
D333
D4444
但是UDP有可能按照以下顺序将所接收的数据提交到服务端的应用:
事实上,UDP协议的这种乱序性基本上很少出现,通常只会在网络非常拥挤的情况下才有可能发生。
UDP-UDP协议的应用
既然UDP是一种不可靠的网络协议,那么还有什么使用价值或必要呢?
其实不然,在有些情况下UDP协议可能会变得非常有用。
因为UDP具有TCP所望尘莫及的速度优势。
虽然TCP协议中植入了各种安全保障功能,但是在实际执行的过程中会占用大量的系统开销,无疑使速度受到严重的影响。
反观UDP由于排除了信息可靠传递机制,将安全和排序等功能移交给上层应用来完成,极大降低了执行时间,使速度得到了保证。
关于UDP协议的最早规范是RFC768,1980年发布。
尽管时间已经很长,但是UDP协议仍然继续在主流应用中发挥着作用。
包括视频电话会议系统在内的许多应用都证明了UDP协议的存在价值。
因为相对于可靠性来说,这些应用更加注重实际性能,所以为了获得更好的使用效果(例如,更高的画面帧刷新速率)往往可以牺牲一定的可靠性(例如,会面质量)。
这就是UDP和TCP两种协议的权衡之处。
根据不同的环境和特点,两种传输协议都将在今后的网络世界中发挥更加重要的作用。
UDP-UDP程序设计
UDPServer程序
1、编写UDPServer程序的步骤
(1)使用socket()来建立一个UDPsocket,第二个参数为SOCK_DGRAM。
(2)初始化sockaddr_in结构的变量,并赋值。
sockaddr_in结构定义:
structsockaddr_in{
uint8_tsin_len;
sa_family_tsin_family;
in_port_tsin_port;
structin_addrsin_addr;
charsin_zero[8];
};
这里使用“08”作为服务程序的端口,使用“INADDR_ANY”作为绑定的IP地址即任何主机上的地址。
(3)使用bind()把上面的socket和定义的IP地址和端口绑定。
这里检查bind()是否执行成功,如果有错误就退出。
这样可以防止服务程序重复运行的问题。
(4)进入无限循环程序,使用recvfrom()进入等待状态,直到接收到客户程序发送的数据,就处理收到的数据,并向客户程序发送反馈。
这里是直接把收到的数据发回给客户程序。
2、udpserv.c程序内容:
#include
#defineMAXLINE80
#defineSERV_PORT8888
voiddo_echo(intsockfd,structsockaddr*pcliaddr,socklen_tclilen)
{
intn;
socklen_tlen;
charmesg[MAXLINE];
for(;
;
)
len=clilen;
/*waitingforreceivedata*/
n=recvfrom(sockfd,mesg,MAXLINE,0,pcliaddr,&
len);
/*sentdatabacktoclient*/
sendto(sockfd,mesg,n,0,pcliaddr,len);
}
intmain(void)
intsockfd;
structsockaddr_inservaddr,cliaddr;
sockfd=socket(AF_INET,SOCK_DGRAM,0);
/*createasocket*/
/*initservaddr*/
bzero(&
servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(SERV_PORT);
/*bindaddressandporttosocket*/
if(bind(sockfd,(structsockaddr*)&
servaddr,sizeof(servaddr))==-1)
perror("
binderror"
);
exit
(1);
do_echo(sockfd,(structsockaddr*)&
cliaddr,sizeof(cliaddr));
return0;
UDPClient程序
1、编写UDPClient程序的步骤
(1)初始化sockaddr_in结构的变量,并赋值。
这里使用“8888”作为连接的服务程序的端口,从命令行参数读取IP地址,并且判断IP地址是否符合要求。
(2)使用socket()来建立一个UDPsocket,第二个参数为SOCK_DGRAM。
(3)使用connect()来建立与服务程序的连接。
与TCP协议不同,UDP的connect()并没有与服务程序三次握手。
上面说了UDP是非连接的,实际上也可以是连接的。
使用连接的UDP,kernel可以直接返回错误信息给用户程序,从而避免由于没有接收到数据而导致调用recvfrom()一直等待下去,看上去好像客户程序没有反应一样。
(4)向服务程序发送数据,因为使用连接的UDP,所以使用write()来替代sendto()。
这里的数据直接从标准输入读取用户输入。
(5)接收服务程序发回的数据,同样使用read()来替代recvfrom()。
(6)处理接收到的数据,这里是直接输出到标准输出上。
udpclient.c程序内容:
voiddo_cli(FILE*fp,intsockfd,structsockaddr*pservaddr,socklen_tservlen)
charsendline[MAXLINE],recvline[MAXLINE+1];
/*connecttoserver*/
if(connect(sockfd,(structsockaddr*)pservaddr,servlen)==-1)
connecterror"
while(fgets(sendline,MAXLINE,fp)!
=NULL)
/*readalineandsendtoserver*/
write(sockfd,sendline,strlen(sendline));
/*receivedatafromserver*/
n=read(sockfd,recvline,MAXLINE);
if(n==-1)
readerror"
recvline[n]=0;
/*terminatestring*/
fputs(recvline,stdout);
intmain(intargc,char**argv)
structsockaddr_insrvaddr;
/*checkargs*/
if(argc!
=2)
printf("
usage:
udpclient\n"
if(inet_pton(AF_INET,argv[1],&
servaddr.sin_addr)<
=0)
[%s]isnotavalidIPaddress\n"
argv[1]);
do_cli(stdin,sockfd,(structsockaddr*)&
运行例子程序
1、编译例子程序
使用如下命令来编译例子程序:
gcc-Wall-oudpservudpserv.c
gcc-Wall-oudpclientudpclient.c
编译完成生成了udpserv和udpclient两个可执行程序。
2、运行UDPServer程序
执行./udpserv&
命令来启动服务程序。
我们可以使用netstat-ln命令来观察服务程序绑定的IP地址和端口,部分输出信息如下:
ActiveInternetconnections(onlyservers)
ProtoRecv-QSend-QLocalAddressForeignAddressState
tcp000.0.0.0:
327680.0.0.0:
*LISTEN
1110.0.0.0:
60000.0.0.0:
tcp00127.0.0.1:
6310.0.0.0:
udp000.0.0.0:
*
88880.0.0.0:
8820.0.0.0:
可以看到udp处有“0.0.0.0:
8888”的内容,说明服务程序已经正常运行,可以接收主机上任何IP地址且端口为8888的数据。
如果这时再执行./udpserv&
命令,就会看到如下信息:
binderror:
Addressalreadyinuse
说明已经有一个服务程序在运行了。
运行UDPClient程序
执行./udpclient127.0.0.1命令来启动客户程序,使用127.0.0.1来连接服务程序,执行效果如下:
Hello,World!
thisisatest
^d
输入的数据都正确从服务程序返回了,按ctrl+d可以结束输入,退出程序。
如果服务程序没有启动,而执行客户程序,就会看到如下信息:
$./udpclient127.0.0.1
test
readerror:
Connectionrefus