一、借鉴说明,本博文借鉴以下博文
1.BlueTzar,TCP/IP四层模型,
http://www.cnblogs.com/BlueTzar/articles/811160.html
2.叶剑峰,漫谈TCP,
http://www.cnblogs.com/yjf512/p/5909031.html
3.bizhu,TCP和UDP的区别(转),
http://www.cnblogs.com/bizhu/archive/2012/05/12/2497493.html
4.任智康,TCP/IP、Http的区别,
http://www.cnblogs.com/renyuan/archive/2013/01/19/2867720.html
二、TCP和UDP
- 基础知识
1.TCP
TCP是一种可靠的、面向连接的字节流服务。源主机在传送数据前需要先和目标主机建立连接。然后,在此连接上,被编号的数据段按序收发。同时,要求对每个数据段进行确认,保证了可靠性。如果在指定的时间内没有收到目标主机对所发数据段的确认,源主机将再次发送该数据段。如图所示,是TCP的数据报格式。
●源、目标端口号字段:占16比特。TCP协议通过使用"端口"来标识源端和目标端的应用进程。端口号可以使用0到65535之间的任何数字。在收到服务请求时,操作系统动态地为客户端的应用程序分配端口号。在服务器端,每种服务在"众所周知的端口"(Well-Know Port)为用户提供服务。
●序列号字段:占32比特。用来标识从TCP源端向TCP目标端发送的数据字节流,它表示在这个报文段中的第一个数据字节。
●确认号字段:占32比特。只有ACK标志为1时,确认号字段才有效。它包含目标端所期望收到源端的下一个数据字节。
●首部长度字段:占4比特。给出头部占32比特的数目。没有任何选项字段的TCP头部长度为20字节;最多可以有60字节的TCP头部。
●标志位字段(U、A、P、R、S、F):占6比特。各比特的含义如下:
◆URG:紧急指针(urgent pointer)有效。
◆ACK:确认序号有效。
◆PSH:接收方应该尽快将这个报文段交给应用层。
◆RST:重建连接。
◆SYN:发起一个连接。
◆FIN:释放一个连接。
●窗口大小字段:占16比特。此字段用来进行流量控制。单位为字节数,这个值是本机期望一次接收的字节数。
●TCP校验和字段:占16比特。对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证。
●紧急指针字段:占16比特。它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。
●选项字段:占32比特。可能包括"窗口扩大因子"、"时间戳"等选项。
滑动窗口
滑动窗口是接收端告诉发送端下次可以发送多少包。好吧,这里也需要面对几个问题:
避免误区:发送方和接受方的请求-响应并不是一一对应的。
网络上并不是只有发送方发一个请求,接收方回复一个ACK这种模式的。他们交互的模式更可能是:发送方一次发送多个请求包,接收方回复一个ACK,把这些请求包都回复了。这个使用前面的Acknowledgment Number是可以做到的。
但是基本上,在接收方的角度,ACK包一定是收到一个包之后,才返回一个ACK,就是说,没有无缘无故的发送重复ACK,没有一个请求,多个ACK这种情况。但是有多个请求,多个重复ACK的情况,这个时候,往往说明某个请求的包丢失了。
为什么需要有滑动窗口存在?
滑动窗口的存在是为了控制网络上包的数量。如果没有滑动窗口,那么就是一个很理想很理想的情况,发送方一有数据,加上包头达到MTU大小,直接发送,就和冲锋枪一样,突突突突。但是呢?这样子,实际上,没有考虑到接收方是否能接收完。接收端就像一个一直在吃饭的胖子,他的吃饭速度是固定的,它一次性最多能吃10碗饭,某个时刻可能已经吃了两碗饭,但是还没消化。所以这个时候,它只能再吃8碗饭了,如果这个时候你一下子给它80碗,必然导致它堵死了,吃不下不吃下。这个滑动窗口就是接收端告诉发送端我还能吃几碗饭的通话器。滑动窗口,限制发送方一次发送的包数量。
为什么叫滑动窗口?
滑动窗口我更愿意理解为发送方和接收方共同维护的。分别有发送窗口和接收窗口区别。
发送方数据有几个状态:数据已发送未收到ACK,数据已发送收到ACK
接收方数据有几个状态:数据已收到未被应用层消费,数据已收到已被应用层消费
把发送数据横拍做长列状,发送方一旦有数据收到ACK,那么滑动窗口左侧边就进行左移。同样,一旦接收方有数据被应用层消费,那么,滑动窗口的右侧边就进行右移。整个过程,就好比努力爬行的蚯蚓,尾巴向前挪一寸,头部再向前走一寸,直到把整个数据都从头到尾移动完毕。
回到TCP的滑动窗口字段,这个字段是接收端回复给发送端,告诉发送端接收端的窗口大小的。我们其实默认也把这个窗口大小叫做滑动窗口大小。
关于滑动窗口的概念的理解,我的感触是网上各种各样对这个滑动窗口的描述,不要陷入到咬文嚼字中,头脑中形象有这个滑动窗口的滑动过程,就可以了,很多文章很多描述可能是前后矛盾的。比如,下面两个关于发送窗口的描述:
- 发送窗口是由滑动窗口和拥塞窗口共同决定的。
- 发送窗口是由接收窗口决定的。
建立连接和释放连接
TCP著名的三次握手和四次挥手
这个图里面的client和server应该理解为发送方和接收方。下面这一串描述请熟练练习到像串口相声一样:发送方发送一个SYN到接收方请求建立连接,接收方返回一个ACK确认收到请求,并携带一个SYN给发送方请求建立双向连接,发送方再返回一个ACK给接收方确认,这个时候连接就建立了。
顺势说下四次挥手吧。发送方发送一个FIN给接收方主动请求断开连接,接收方返回一个ACK确认,接着接收方再发送一个FIN请求断开另一方向的连接,发送方收到之后返回一个ACK确认。这个时候,连接就中断了。
2.UDP
UDP是一种不可靠的、无连接的数据报服务。源主机在传送数据前不需要和目标主机建立连接。数据被冠以源、目标端口号等UDP报头字段后直接发往目的主机。这时,每个数据段的可靠性依靠上层协议来保证。在传送数据较少、较小的情况下,UDP比TCP更加高效。如图所示,是UDP的数据报结构。
●源、目标端口号字段:占16比特。作用与TCP数据段中的端口号字段相同,用来标识源端和目标端的应用进程。
●长度字段:占16比特。标明UDP头部和UDP数据的总长度字节。
●校验和字段:占16比特。用来对UDP头部和UDP数据进行校验。和TCP不同的是,对UDP来说,此字段是可选项,而TCP数据段中的校验和字段是必须有的。
- 相关知识:套接字
在每个TCP、UDP数据段中都包含源端口和目标端口字段。有时,我们把一个IP地址和一个端口号合称为一个套接字(Socket),而一个套接字对(Socket pair)可以唯一地确定互连网络中每个TCP连接的双方(客户IP地址、客户端口号、服务器IP地址、服务器端口号)。如图所示,是套接字的示意图。
需要注意的是,不同的应用层协议可能基于不同的传输层协议,如FTP、TELNET、SMTP协议基于可靠的TCP协议。TFTP、SNMP、RIP基于不可靠的UDP协议。
同时,有些应用层协议占用了两个不同的端口号,如FTP的20、21端口,SNMP的161、162端口。这些应用层协议在不同的端口提供不同的功能。如FTP的21端口用来侦听用户的连接请求,而20端口用来传送用户的文件数据。再如,SNMP的161端口用于SNMP管理进程获取SNMP代理的数据,而162端口用于SNMP代理主动向SNMP管理进程发送数据。
还有一些协议使用了传输层的不同协议提供的服务。如DNS协议同时使用了TCP 53端口和UDP 53端口。DNS协议在UDP的53端口提供域名解析服务,在TCP的53端口提供DNS区域文件传输服务。