TCP协议讲解(一)
TCP协议属于应用层协议,其格式为:
源端口号: 16bit,注意并不是IP地址,是应用的端口号,0~65535之间;
顺序号: 32bit,来标识从TCP源端向TCP目标端发送的数据字节流的序号,例如一个报文序号段是100,返发送的数据是200字段,则下一个报文序段号应为301;
确认号: 32bit,只有ACK为1时,这个才有效,包含目标端所期望收到源端的下一个数据字节;
首部长度: 4bit;需要这个值是因为任选字段的长度是可变的。这个字段占4bit,最多表示15,也就是有15个32bit的数据,因此TCP最多有60字节的首部。然而,没有任选字段,正常的长度是20字节。“任选字段”指的“可选项”和数据部分,这些是可变的。
URG: 1bit,紧急指针;
ACK: 1bit,确认***;
PSH: 1bit,接受方应该尽快将这个报文段交给应用层;
RST: 1bit,重建链接;
SYN: 1bit,发送链接;
FIN: 1bit,释放链接;
窗口大小: 16bit,接受缓冲区,用来告诉TCP链接对方端自己能接受的最大长度;
紧急指针: 只有URG标识位为1时才有意义;
TCP提供了一种面向连接的,可靠的字节流服务。所以TCP在通信前必须建立连接,在一个TCP连接中只有两方进行连接,所以广播是不能运用在TCP上的。
TCP的三次握手中涉及到了ACK,SYN,req等,这是做什么的?
抛开三次握手,就讲TCP在2个端之间的传递数据:TCP在一次传输数据时大概是传1400个字节,日常开发中,如果要传输10MB的数据,需要发送7100多个包,发送时,TCP协议为每个包编号(seq),以便接受方按照顺序还原,万一丢包,也可以知道丢失的是哪个包。第一个包编号是随机数,假设是1,如该数据负载长度为100,则第二个包编号为101;所以每个数据包可以会有两个编号:自身的编号和下一个的编号。接受方可以方便排序。
TCP的慢启动和ACK:
服务器发送数据当然越快越好,一次性全发出去最简单,但是受路由器过热,带宽小,缓存溢出等影响,会导致丢包,速度越快,丢的越多,那么如何做到平衡呢?慢慢试!刚开始慢点发,根据丢包情况调整速率,确认可以了,就快点发。;ACK是确认字段,默认当接收方收到2个TCP数据包就发送一个确认消息,就是ACK。
ACK携带2个信息:
1.期待要接收下一个数据的编号,就是告诉发送方,下一个数据从哪个编号发给我;
2.接受方接受窗口的剩余容量:
根据这两个信息,再加上自己发送的数据包的最新编号,可以退出接受方大概的速率;
其中一次发送的数据大小叫做“发送窗口”,这个数字是可变的。
请看懂下图:
起初A(左)发了一个seq=1的包,告诉B(右)我是从编号1开始发包的,ack=1表示,我希望你是从编号1开始发包的,length=100,表示我这次要给你发100字节的数据。B收到后就按照要求从编号1发了一个包,所以seq=1,并告诉A,我希望你从编号101开始给我发包(说明B已经收到100字节了),我这次给你发200字节的数据,A收到后按照要求从101开始发包,所以seq=101,并告诉B,我希望你从201开始发包,我这次给你发50字节数据,B再同样回复即可。
丢包了怎么办?
如果正常收到包,ACK是会加1的,如果4号包丢失了,ACK不会加1,接收端会一直反给发送端之前的ACK,连续3次后,发送方会确认丢包,重发!
疑问:上面的ACK和TCP报文里面的ACK是不是一样的?很显然不是,TCP报文的ACK只有1bit,只有0或1的状态,怎么可能会有201,101等等,名字一样而已。