TCP Protocal
1 Introduction
1.1 TCP服务
1.1.1 TCP服务特性:
- 面向连接:connection-oritented
- 可靠:reliable
- 字节流:bytes stream
1.1.2 面向连接
意思是使用TCP通信的双方在进行数据交换前必须建立TCP连接
1.1.3 可靠
TCP通过如下几个方面提供可靠的连接:
- 将应用数据分割为TCP认为合适大小的数据块进行传输。这与UDP不同。
- 定时器。TCP在传输segment的时候会维护一个定时器,等待另一端对这个segment的接受确认。如果在规定的时间内没有确认接受,TCP将进行重传
- 接受数据后,会发送确认,但不会立即发送,而是延迟a fraction of second
- 对TCP的头部和数据进行校验和,如果到达的segment是个无效的校验和,TCP将丢弃segment并不进行确认
- 排序.tcp segment是封装在ip datagram中的,而ip datagram的到达是无序的,tcp可以根据需要排序后发给上面的应用层
- 去重.ip datagram会出现重复的数据包,tcp负责丢弃重复的数据
- flow control.TCP连接的双方都有一个有限的大小的缓冲区,当接收方的缓冲区被发送方发送的数据填满的时候,会暂停继续接受。
1.1.4 byte stream service
TCP传输的是字节流,并不会对数据插入边界记录。比如,TCP连接的一段写了10个字节,接着又写了20个字节,然后又写了50个字节。对于接受端并不知道每次各写了多少字节, 他可能将这80个字节分四次读取,每次读取20字节。 其次TCP并不会对字节流数据进行解析,TCP并不知道字节流中的数据是二进制,还是ASCII或者其他。
1.2 TCP header
TCP首部,在没有options的情况下为20字节。TCP segment包含了源端口和目标端口,标识了发送和接受的应用。IP加端口有时称为socket
。四元组定义一个TCP连接。
sequence number: sequence number标识了当前segment中由发送方到接受方的数据中第一个字节的位置。其为一个32位无符号整数,从0到2^32 - 1. sequence number字段包含initial sequence number(ISN).ISN是host指定用于创建连接的,所以发送数据的第一个字节的sequence number应该是ISN + 1,因为SYN 标志位发送的时候消耗了 一个sequence number.同样在关闭连接的时候,FIN标志位的发送也会消耗一个sequence number.
发送ACK不需要消耗sequence number等任何东西,因为 acknowledgment number本省就是tcp header的一部分。因此连接一旦建立,ACK标志位是一直处于打开的状态。
TCP给应用层提供了全双工的服务,这意味着数据流动的双发是相互独立的,因此连接的双方都必须在每个数据流动方向上维护自己的数据顺序号。
header length字段给出了header的长度,以32-bit word为单位,是一个站4个bit的字段,因此,header的最大长度为4个bit位全位1的时候,即十进制数15,乘以其单位32-bit word(4个字节),即 15 * 4 = 60 bytes。在没有option的时候,header正常大小是20bytes.
TCP header中有6个标志位:URG ACK PSH RST SYN FIN URG: 需要发送方将紧急数据发给另一端 ACK: acknowledgment number PSH: 接受者需要尽快将数据发给应用层 RST:reset connection。IP 冲突时会RST SYN:同步顺序号,建立连接 FIN:结束发送数据
checksum: TCP首部和TCP数据的校验和,强制字段 option字段:option字段通常为maximum segment size, MSS.连接双方通常会在第一个segment中指定这个选项,表明自己可以接受的MSS。
2 TCP connection establishment and termination
TCP是面向连接的协议,在发送数据前,双发必须先建立连接。
2.1 Connection Establishment and Termination
2.1.1 建立连接
为什么要三次握手?三次握手考察的是client与server的发送,接收的能力。通过三次握手,待连接的双方都经历了发送和接受两个阶段。对于client和server都各自维护了自己的sequence number,而ack 则是将对方的sequence number + 1作为自己ack的值。如:
1 0.0 svr4.1037 > bsdi.discard: s 1415531521:1415531521(0) win 4096 <mss 1024>
2 0.002402 (0.0024) bsdi.discard > svr4.1037: s 1823083521:1823083521(0) ack 1415531522 win 4096 <mss 1024>
3 0. 007224 (0.0048) svr4.1037 > bsdi.discard: . ack 1823083522 win 4096
4 4.155441 (4.1482) svr4.1037 > bsdi.discard: F 1415531522:1415531522(0) ack 1823083522 win 4096
5 4.156747 (0.0013) bsdi.discard > svr4.1037: . ack 1415531523 win 4096
6 4.158144 (0.0014) bsdi.discard > svr4.1037: F 1823083522:1823083522(0) ack 1415531523 win 4096
7 4.180662 (0.0225) svr4.1037 > bsdi.discard: . ack 1823083523 win 4096
上面的内容是通过tcpdump工具得到的。第一行中的1415531521: 1415531521 (0)
意思是:本packet的sequence number是1415531521,本segment中的数据为0字节。这个字段的格式为:
起始顺序号:结束顺序号 (segment中包含数据字节数)
这个字段仅在下面两种情况下出现:
- segment中包含的1个或更多字节的数据的时候
- 当SYN,FIN,RST标志位打开的时候
在第2行中,ack 1415531522
字段表示 acknowledgment number为1415531522,是第一行中的顺序号+1.这个字段在TCP首部中ACK标志位打开的时候会出现。
每行中都出现的win 4096
字段,是发送者建议的window size,因为在上面的示例中没有发送任何数据,所以window size没有改变,一直是默认值4096.
上面输出的最后一个字段<mss 1024>
是由发送者指定的maximum segment size(MSS)选项,意思是发送者不想接受大于此值的TCP segment.这通常用于避免数据分段。
2.1.2 断开连接
众所周知,建立连接需要3个segments,而断开连接需要4个segments.需要4个segments的原因是:TCP的half-close.由于TCP连接是全双工的,(意思是一个方向的数据流动独立于另一个方向的数据流动) 所以每个流向需要独立关闭。规则是任何一端在数据发送完成后,就可以发送FIN。当TCP接受到FIN后,它必须告诉应用程序:另一端关闭了那个方向的数据流。发送FIN通常是应用程序声明了close。
接受到FIN表明那个方向不会有数据发送过来,但接收到FIN的这一方仍然可以发送数据。应用程序可以使用half-close,但实际中很少这么用。
上面的示例是通过Telnet的客户端建立的tcp连接。当客户端输入quit的时候,client发送了一个FIN,表示正在关闭从client到server的数据流向。 server接收到FIN后,会发送一个将接受的sequence number + 1的ACK。如同SYN,FIN也会消耗一个顺序号。同时server的TCP会给应用程序发送end-of-file。接着关闭连接,发送FIN。然后client必须 在接收到的sequence number上加1,做为ACK发送给server。
2.2 建立连接超时
有几种情况连接建立不成功,其中之一就是server宕机。
2.3 Maximum Segment Size
MSS是TCP能发送到另一端的最大的数据块。