聊到网络协议,我们常常会想到OSI(Open System Interconnection 开放式系统互联)七层模型、TCP/IP协议簇,她位于OSI、TCP/IP协议簇哪一层等问题。 如下图OSI七层模型及对应的TCP/IP协议簇所示,TCP位于OSI中的第四层(传输层)。位于TCP/IP协议簇中的第四层(TCP or UDP)。
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license()" for more information.
>>> from socketserver import BaseRequestHandler, TCPServer
>>> class EchoHandler(BaseRequestHandler):
def handle(self):
print('Got connection from', self.client_address)
while True:
msg = self.request.recv(8192)
if not msg:
break
self.request.send(msg)
>>> if __name__ == '__main__':
serv = TCPServer(('', 20000), EchoHandler)
serv.serve_forever()
Got connection from ('127.0.0.1', 59006)
复制代码
客户端代码:
wangyongwangdeiMac:~ wangyongwang$ python
Python 2.7.15 (default, Oct 2 2018, 11:47:18)
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from socket import socket, AF_INET, SOCK_STREAM
>>> s = socket(AF_INET, SOCK_STREAM)
>>> s.connect(('localhost', 20000))
复制代码
上述代码的效果如下图所示:
如上图,Got connection from ('127.0.0.1', 62515)我们可以确定客户端使用的端口是 59006 。
通过上述准备工作,下边笔者会使用Wireshark捕获TCP请求响应的整个过程,并进行相应分析。
TCP三次握手
TCP通过三次握手建立连接,我们对下图应该比较熟悉:
对上图中的代号及下文中的代号做说明:
Seq 即下文中的 Sequence number ,序列号是指发送数据的位置。每发送一次数据,就累加一次该数据字节数的大小。一般用Wireshark捕获我们平时的请求的Seq是一个随机数。
Ack 即 Acknowledgement number ,是指下一次应该受到的数据的序列号。
SYN 为Flags部分的 Syn ,Syn为1表示希望建立连接。
ACK 为Flags部分的 ACK ,Ack为1表示确认应答的字段变为有效。
TCP第一次握手,客户端向服务端发送报文,关键信息为Syn=1,Seq=0。如下图所示,sequence number= x = 0,Syn=1。
TCP第二次握手,服务端向客户端发送报文,关键信息为Ack=x+1=1,Syn=1,Seq=y=0。如下图所示,sequence number=y=0,Ack=x+1=1 , Syn = 1。