TCP/IP是普遍使用的网络互连标准协议,可在不同环境和不同节点之间进行彼此通信,是连入Internet的所有计算机在网络上进行各种信息交换和传输所必须采用的协议,也是Windows NT、Windows 2000 Server、NetWare及UNIX互连所采用的协议。TCP/IP实际上是一种层次型协议,它的内部包含许多其他的协议,组成了TCP/IP协议组,其协议层次表如下:
表1 TCP/IP协议层次
应 用 层 |
HTTP、Telnet、FTP、SMTP、SNMP |
传 输 层 |
TCP、UDP |
网 间 网 层 |
IP(ARP、RARP、ICMP) |
网络接口层 |
Ethernet、X.25、SLIP、PPP |
TCP/IP协议实际上就是在物理网上的一组完整的网络协议,其中TCP是提供传输层服务,而IP则是提供网络层服务。TCP/IP协议的核心部分是传输层协议(TCP、UDP),网络层协议(IP)和物理接口层,这三层通常是在操作系统内核中实现。
图1 TCP/IP各层次协议
下面重点介绍传输层中TCP与UDP,及其区别。
一、用户数据报协议UDP
用户数据报协议UDP(User Data Protocol)是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单、不可靠信息传送服务;UDP 协议基本上是 IP 协议与上层协议的接口;UDP 协议适用端口分别运行在同一台设备上的多个应用程序;它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去。UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。比如,我们经常使用“ping”命令来测试两台主机之间TCP/IP通信是否正常,实际ping命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包到达的消息及时反馈回来,那么网络就是通的。
UDP数据包中源端口和目标端口字段指定了两个16长的端口号,其中源端口字段是可选的,如果指定了该字段的值,就表示相应的数据包应发往的端口号,如果不使用,应将其设为0。长度字段表示整个UDP数据包的8位字数,包含UDP头部和数据部分。因此,该字段的值最小为8。如图示:
图2 UDP数据报格式
UDP协议位于IP协议之上,即UDP数据包是封装在IP数据包中进行传输的。
UDP头部 |
UDP数据区 |
IP报头 |
IP报文数据区 |
帧头 |
帧数据区 |
图3 UDP数据包封装关系
下面解释一个使用UDP协议的应用程序时如何将数据传输到目的主机A的特定应用程序的。首先接受数据的应用程序要申请一个UDP端口号,设为P。发送方的应用程序准备数据后,将其交给UDP协议,让其将数据发送给主机A的端口P。UDP协议将应用程序的数据作为UDP数据包的数据部分封装在一个UDP数据包中,并将数据包的目标端口字段设置为P。UDP协议再将包交给IP协议处理,让其将该数据包发送到主机A。IP协议将UDP数据包作为IP数据包的的数据封装在一个IP数据包中,并将目的地址设置为A,将协议字段设置为17,然后将其交给网络层处理并发送出去,该IP数据包可能会经过数个路由器,并最终到达主机A的IP协议层。主机A的IP协议发现字段为17,就将IP数据包的数据区交给UDP协议处理。UDP协议发现端口号为P,就将UDP数据包的数据区放置在端口P的队列中。A的应用程序从该队列中将数据取出进行处理。
二、传输控制协议TCP
传输控制协议TCP(Transmission Control Protocol)是基于连接的协议,即是在正式通信前必须要与对方建立起连接。一个TCP连接必须要经过三次“握手”才能建立起来,这三个简单过程包括主要:主机A向主机B发出连接请求数据包;主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包;主机A再发出一个数据包确认主机B的要求同步。三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。
TCP协议向应用程序提供的服务时面向字节流的,TCP数据的传输时通过IP协议进行的,IP协议的传输单位是IP数据包。因为用户提供的字节流数据可能很大,而一个IP数据包所能容纳的数据是有限的,因此TCP协议必须将字节流数据进行分割并组织成IP数据包进行传输,在目标主机的TCP协议将这些分割的数据再组织成数据流。TCP协议数据包有自己的头部和数据包,一个TCP数据包成为段。源端口和目标端口用于指定发送发和接收方的TCP端口号。和UDP协议不同的是,TCP段中源端口号必须指定。这是因为TCP是面向连接的,一个TCP连接由发送方和接收方的IP地址和TCP端口号组成。因为一个TCP端口号可以为不同的链接所中用,所以两个端口号中缺少一个都无法确定该数据段所属的TCP链接,也就无法确定处理数据的应用程序了。下图就是TCP数据段的具体格式:
图4 TCP报文格式
TCP连接的建立需要进行三次连接信息的发送/接收。三次握手的目的主要是在于同步连接双方发送数据的初始序列号。首先,连接的主动打开方式(即连接请求方)向被动打开方(即连接接受方)发送一个TCP数据段,该TCP段通常不包含数据区,并将代码位中SYN位置1设在序列号字段设置一个初始序列号。被动打开方接收到这个链接请求段后,向主动打开方发送一个TCP段。将ACK位置1,表示已经收到了主动打开方的连接请求。被动打开还会将SYN位置1并在序列号字段设置自己的初始序列号。主动打开方收到被动打开方的TCP段之后会发送一个ACK给被动打开方,接收方收到该数据段后连接的建立就完成了,就可以开始传输数据了。
图5 TCP建立连接的三次握手过程
三、TCP与UDP的比较
因为UDP协议无连接,所以它的通信效率高;也正因如此,它的可靠性不如TCP协议高。
TCP提供的是可靠的传输服务,而UDP协议提供的是不可靠的服务。UDP协议没有流量控制机制,如果发送进程发送数据报塞满了接收进程的接收缓冲区,就会丢弃数据报,而出现这种情况,UDP协议不会通知发送进程减缓数据的发送速率。TCP协议则拥有流量控制,具体机制暂略。
TCP提供的是面向字节流的服务。应用程序只需将要传输的数据以字节流的形式提交给TCP协议,在连接的另一段,数据以同样的字节流顺序出现在接收程序中。而UDP协议的传输单位是数据块,一个数据块只能封装在一个UDP数据包中。
TCP不适用于只有少量数据传输的情况,因为连接的开销较大,这么做得不偿失;此外TCP也不适用于实时应用,因为TCP协议对数据的传输是有先后顺序的,只有前面的传输成功才会开始后面的数据传送,这显然不符合实时应用的要求。
对于不适合使用TCP协议的应用就只能使用UDP协议,使用UDP协议进行通信时应用程序必须自己处理下列问题:(1)应用程序必须自己提供机制来保证可靠性。应用程序必须有自己的超时重发机制、数据失序的处理、流量控制等。当然对于一些可靠性要求不高的应用可以不用这些机制,但通常都需要区分数据的先后关系。(2)应用程序必须处理大块数据的分割,以让其能封装在一个UDP数据包中。在接收方还必须再将分割的数据进行重组。
UDP协议中,发送进程在发送每个数据报的时候并不等待多个数据报集中在一起以一个较大数据报发送出去,而是立即发送出去,它是记录型的协议。并且接收进程每次通过read或recv获得的数据报必定是发送进程所发送的那个数据报,不可能是多个数据报,接收进程可以识别到发送进程所发送的每个数据报的记录边界;TCP协议中发送进程在发送每个数据报的时候在内核处理过程中有可能并不立即发送出去,而是会将多个数据报集中在一起以一个较大的数据报来发送,它是字节流的协议。而接收进程每次通过read来读取发送进程发送过来的数据报并不一定是发送进程原先发送数据报,接收进程无法识别每个数据报的记录边界,所以TCP协议就是字节流的、无记录边界的协议。如QQ聊天所用到的协议就应该是有记录边界的,聊天过程中是以“消息”为单位,消息可以看成一个记录,所以QQ聊天协议采取UDP协议而不是TCP协议。
UDP协议是无序的传输协议。发送进程所发送的每个数据报并不按照原先发送的顺序到达接收进程,有可能早发送的数据报较后到达接收进程,因为数据报在经过中间路径的传送时会因为各个数据报传送的路径不同或者其它原因而造成这些数据报到达的顺序不同,为了使基于UDP协议的应用程序有序,必须在应用程序中设置序号、确认机制来使其有序,TFTP协议是基于UDP的协议;TCP协议是有序协议,有超时、序号、重传、确认机制。如FTP协议是基于TCP用于传送文件的协议,FTP协议中的控制连接传送的内容都是基于消息形式,客户端在控制连接上发出一个请求消息,服务器端返回一个请求结果消息,因为控制连接上是交互式的消息传送,客户端在发送一个请求之后,在服务器端的响应消息未到达之前,客户端是不会发送第二个请求消息的,所以对于交互式的消息传递采用TCP协议使我们不必担心两个请求消息会叠加在一起。
UDP协议在创建插口之后,可以同多个服务器端建立通信,而TCP协议只能与一个服务器端建立通信,TCP不允许目的地址是广播或多播地址,而UDP允许;UDP协议客户端同服务器端的通信关系可以是一对多的关系,而TCP协议只能是一对一的关系。
表2:客户端连接过程
表3:服务器端连接过程