重学TCP协议(一)

重学TCP协议(一)

目的:重新梳理TCP,全局理解协议中的细节,知道是怎样实现的,理解为什么要这样做,了解可能会带来什么问题。

PS:图片有空了慢慢贴。

 

 

 

简要介绍:

TCP协议是基于网络层IP协议的传输层协议,提供一种面向连接的,可靠的字节流服务(byte stream service )。在TCP连接中, 仅支持两方进行彼此通信。

TCP的可靠性由以下方式 来提供:

1) 恰当的数据分段。即将字节流根据MSS来封包发送。

2) 确认机制、重传机制。

3) 首部的检验和。

4) 网络层的IP数据报可能会失序,因此TCP需要将数据进行重新排序。

5) 数据报可能会重复,必须恰当的丢弃重复的数据报。

6) TCP提供流量控制,可根据另一端的缓冲区情况发送恰当的数据(滑动窗口协议)。

7) TCP协议对字节流不作解释。由应用层对数据进行语义上的解释。

 

随便抓个包:

 

IP数据头

 

TCP数据头

 

头部中比较重要的数据结构

源端口,目的端口,序号,确认序号。 标志位,窗口大小。

URG:紧急指针,一般用不上,忽略。

ACK:经常用,接收端发给源端,确认前一个包已收到。

PSH:个人没怎么碰到过。

RST:可以理解为重置连接,普通情况下当目标端口未开放会发送此RST回来,此外,连接中间的防火墙等网络设备也会发。

 

SYN:发起连接的标志,SYN Flood是基于的一种DOS攻击手法。

FINshutdown 时发送,告诉对方,我这边完成了,要送掉连接了。

 

 

 

1、 TCP连接的建议,三步握手。

1) 源端发送SYN到服务器,表示喜娃怀与服务器的某个端口建立TCP连接,在TCP首部带上初始的序号(client ISN)。此报文中设置SYN=1

2) 服务器返回SYN包,带上服务器的初始序号(server ISN),并且ACK=client ISN+1设置SYN=1,ACK=1

3) 源端返回服务器ACK包,  ack = server ISN+1;

 

PS:这边的Seq居然从0开始,之前都没注意过~~

 

关于ISN的选择,根据文献内容,应当随时间变化,避免网络中被延迟的分组被重新传递后导致的错误解释。

2、 TCP连接的终止,四步握手。

1) 首先关闭的一方(A)发送FIN包。FIN在应用层、开发者面前就是socket.read 将返回EOF

2) 接受端(B)返回FINACK包。

3) B关闭连接,发送FIN

4) A发送ACK

 

关闭阶段存在另外两衍生的流程。1 23 两步可以合并, B端无数据发送时,无需发放两个包,可以在一个包里面同时设置FIN+ACK,也就是上面的截图。2)当仅一端调用shutdown,另一端还存在数据发送时,存在半关闭连接的情况。即第2步结束后,B端继续发送数据,A端对这些数据仍然发送ACK,一直到B端发送FIN

 

以下是一个简单的client + server 测试代码,通过简单的Sleep可以看出, 当收到FIN包时,缓冲区的数据仍然存在,仅在后面多了一个EOF而已。

 

 1  # !/usr/bin/env python
 2  import socket
 3  import time
 4  
 5 host= " 192.168.5.106 "
 6 port=10000
 7 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 8 s.bind((host,port))
 9 s.listen(5)
10 sock,addr=s.accept()
11  print  " got connection form  ",sock.getpeername()
12  while 1:
13   data=sock.recv(1)
14   time.sleep(0.1)
15    if  not data:
16      print( " ~~~~~ ")
17      break
18    else:
19  print data
20  


 

1  # !/usr/bin/env python
2  import socket
3 host= " 192.168.5.106 "
4 port=10000
5 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
6 s.connect((host,port))
7 s.send( " hello from client ")
8 s.close()

 

 

你可能感兴趣的:(重学TCP协议(一))