43

网络通信协议之 TCP

 5 years ago
source link: https://mp.weixin.qq.com/s/iAs1qJogHG6r-W77lA9sIw?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

女主宣言

笔者最近看了关于Python的部分内容,发现网络编程部分非常容易能够创建一个本地TCP服务器,正好可以用来分析一下TCP的请求和响应过程。

在本篇文章,笔者将给大家介绍下TCP建立连接(三次握手),传输数据,断开连接(四次挥手)的过程。

PS:丰富的一线技术、多元化的表现形式,尽在“ 360云计算 ”,点关注哦!

TCP简介

  • TCP: TCP(Transmission Control Protocol 传输控制协议)是一种面向 连接的、可靠的、基于字节流传输层通信协议 ,由IETF的 RFC 793 定义。

  • 聊到网络协议,我们常常会想到 OSI (Open System Interconnection 开放式系统互联)七层模型、TCP/IP协议簇,她位于OSI、TCP/IP协议簇哪一层等问题。

    如下图OSI七层模型及对应的 TCP/IP

    协议簇

    所示,TCP位于OSI中的第四层(传输层)。位于TCP/IP协议簇中的第四层(TCP or UDP)。

下图为 OSI七层模型及对应的TCP/IP协议簇

IBVzInm.jpg!web

OSI TCP/IP Family

  • TCP是 面向连接 的,是指客户端在发送、接收数据之前需要先建立连接,这个连接过程需要 三次握手 来完成,笔者借助Python搭建了一个本地的TCP服务,并使用 Wireshark (Wireshark(前称Ethereal)是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。)

    捕获了本地的TCP服务器和TCP客户端之间请求响应的过程,带大家一起看一下建立连接(三次握手),传输数据,断开连接(四次挥手)的过程。

本地搭建TCP服务准备工作:

笔者在前文提到了要用Python创建一个本地TCP服务器,并且分析TCP的请求响应过程。这里笔者使用的是PythonIDE、Mac自带的终端简单创建了一个本地TCP服务端和客户端。

笔者会分析的过程如下:

-> 创建并且启动一个端口号为20000的TCP服务端

-> 创建客户端并和服务端建立连接(三次握手)

-> 客户端向服务端发送数据'AB'

-> 服务端到数据后给客户端发送数据'AB'

-> 服务端收到数据向客户端发送收到的数据(当前即'AB')

-> 客户端和服务端断开连接(四次挥手)

-> 使用Wireshark对建立连接(三次握手),传输数据,断开连接(四次挥手)的过程进行分析

服务端代码:

客户端代码:

上述代码的效果如下图所示:

bmAreej.jpg!web

TCP请求响应效果图

vMvuQbv.jpg!web

TCP建立连接效果图

如上图,Got connection from ('127.0.0.1', 62515)我们可以确定客户端使用的端口是 59006

通过上述准备工作,下边笔者会使用Wireshark捕获TCP请求响应的整个过程,并进行相应分析。

TCP三次握手

  • TCP通过三次握手建立连接,我们对下图应该比较熟悉:

yMJzauJ.jpg!web

TCP三次握手图解

对上图中的代号及下文中的代号做说明:

Seq 即下文中的 Sequence number ,序列号是指发送数据的位置。每发送一次数据,就累加一次该数据字节数的大小。一般用Wireshark捕获我们平时的请求的Seq是一个随机数。

AckAcknowledgement number ,是指下一次应该受到的数据的序列号。

SYN 为Flags部分的 Syn ,Syn为1表示希望建立连接。

ACK 为Flags部分的 ACK ,Ack为1表示确认应答的字段变为有效。

TCP第一次握手,客户端向服务端发送报文,关键信息为Syn=1,Seq=0。如下图所示,sequence number= x = 0,Syn=1。

faqAJni.jpg!web

TCP第一次握手

TCP第二次握手,服务端向客户端发送报文,关键信息为Ack=x+1=1,Syn=1,Seq=y=0。如下图所示,sequence number=y=0,Ack=x+1=1 , Syn = 1。

YbYBZfe.jpg!web

TCP第二次握手

TCP第三次握手,客户端向服务端发送报文,Seq=x+1=1,Ack=y+1=1,ACK=1。如下图所示,Seq=x+1=1,Ack=y+1=1,ACK=1。

bQVfyaZ.jpg!web

TCP第三次握手

我们可以发现在三次握手之后,还有一次TCP Window Update。

jMjmUn6.jpg!web

TCP Window Update

TCP Window Update 是TCP通信中的一个状态,它可以发生的原因有很多,但最终归结于发送者传输数据的速度比接收者读取的数据还快,这使得接受端的在缓冲区必须释放一部分空间来装发送过来的数据,然后向发送者发送Windows Update,告诉给 发送者 应该以多大的速度发送数据,从而使得数据传输与接受恢复正常。参考:tcp三次握手

从上图TCP Window Update,根据Source Port:20000及Destination Port:59006可知,当前发送者是客户端,解释下上一段文字的意思是,客户端发送的数据太快,服务端读书数据慢,服务端向客户端发送了一个TCP Window Update的报文。

上述内容就是TCP建立连接的过程,下边笔者给大家介绍下传输数据部分的内容:

TCP的数据传输过程:

查看数据传输过程和之前建立连接部分,用的是下图代码进行的分析:

mMfQBrq.jpg!web

代码内容和之前建立连接的代码一样,只是添加了 发送数据断开连接 的几行代码。可见这次客户端分配的端口号为 53262

在分析数据传输过程之前,笔者先对下边会用到的名词及工具做个简单说明:

字节byte ,比特即 bit ,1个字节(byte)=8个比特(bit)。

ASCII码:是基于 拉丁字母 的一套电脑编码系统,主要用于显示现代 英语 和其他 西欧 语言。它是现今最通用的单 字节 编码系统

ASCII码对照表

举个例子'A'的ASCII码为0x41

基本的16进制、2进制、10进制之间的转换:

16进制0x41对应2进制为 0100 0001对应10进制为4 * 16 + 1 = 65

在线进制转换

下边笔者带大家看一下数据传输部分的分析:

下图表示客户端s.send(b'A')以二进制形式传输'A'(其对应的ASCII码为65)传输过程:

ZjumIb2.jpg!web

客户端到服务端

下边展示一个客户端s.send(b'AB')并且服务端给予相应的回应(服务端也给客户端发送收到的'')的过程

  • 接收数据的部分Flags中的Acknowledgement 设置为1,表示确认应答的字段有效

  • 接收数据的部分Flags中的Push 设置为1表示表示接收方应该尽快把数据传给上层应用协议

源端口53262目的端口20000 可以看出,下图表示 客户端向服务端发送消息 ,发送的数据为'AB','AB'的ASCII码为0x4142。

2AJVFvV.jpg!web

客户端向服务端发送消息

源端口20000目的端口53262 可以看出下图表示 服务端向客户端 反馈收到了消息。

Acknowledgement number 为4是因为,服务端接接收了客户端的2个字节的数据,在之前的客户端的Sequence number的基础上加了2。

Z3I7B3I.jpg!web

服务端到客户端收到消息响应

源端口20000目的端口53262 可以看出,下图表示 服务端向客户端 发送消息,发送的数据为'AB','AB'的ASCII码为0x4142。

I7vEVbF.jpg!web

服务端给客户端发送消息

源端口53262目的端口20000 可以看出下图表示 客户端向服务端 反馈收到了消息。Acknowledgement number 为4是因为,客户端接收了服务端的2个字节的数据,在之前的服务端的Sequence number的基础上加了2。

2aeAzqI.jpg!web

客户端收到服务端消息后的响应

TCP断开连接四次挥手

TCP断开连接示意图如下:

B3MnIbn.jpg!web

TCP断开连接示意图

对应的Python的客户端代码s.shutdown(2),客户端主动断开连接的。

  • 断开连接的Flags中Fin是设置为1的,表示希望断开连接。

  • 断开连接的Flags中Ack是设置为1的,表示确认应答字段有效。

响应的Wireshark抓包分析如下:

TCP断开连接第一次挥手,从 源端口53262到目的端口20000 ,可以看出是客户端主动断开连接的。Flags中的Fin是设置为1的,Sequence number为7。

uiIVvqA.jpg!web

TCP断开连接第一次挥手

TCP断开连接第二次挥手,从 源端口20000到目的端口53262 ,可以看出是服务端给予客户端断开连接的响应。并且Acknowledge number对之前的客户端的Sequence number做了加1操作。

736BvaB.jpg!web

TCP断开连接第二次挥手

TCP断开连接第三次挥手,从 源端口20000到目的端口53262 ,Flags中的Fin是设置为1的,可以看出是 服务端向客户端发送断开连接 的。Sequence number为7。

q2iMbar.jpg!web

TCP断开连接第三次挥手

TCP断开连接第四次挥手,从 源端口53262到目的端口20000 ,可以看出是 客户端给予服务端断开连接的响应 。并且Acknowledge number对之前的服务端的Sequence number做了加1操作。

Ezqai2Q.jpg!web

TCP断开连接第四次挥手

下边,笔者贴出了IP和TCP首部及Wireshark捕获TCP请求过程的的图。有兴趣的读者可自行做简单分析。

u6ZbAnU.jpg!web

TCP数据在IP数据报中的封装及TCP包首部

  • 后来和昆哥一起交流,经过昆哥指正,上图的TCP首部已经更新过了,较新的TCP首部格式如下:

MbmqYjn.jpg!web

TCP首部

下图为TCP首部中的控制位部分

RzeaMnJ.jpg!web

控制位 Control Flag

RFbuIb6.jpg!web

TCP

VvAVfum.jpg!web

TCP

参考内容:

  • Wireshark数据包实战讲解

  • TCP/IP详解

  • 图解TCP/IP

  • https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.halc001/ipcicint_protocol.htm

  • https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml

  • https://python3-cookbook.readthedocs.io/zh_CN/latest/c11/p02_creating_tcp_server.html#id1

360云计算

由360云平台团队打造的技术分享公众号,内容涉及 数据库、大数据、微服务、容器、AIOps、IoT 等众多技术领域,通过夯实的技术积累和丰富的一线实战经验,为你带来最有料的技术分享

FBNfUf2.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK