网控科技网

同时,在应答数据包中会设置请求和应答的值

简介: 同时,在应答数据包中会设置请求和应答的值,具体参考图3.客户端回复连接确认: 最后,客户端再次发送一个连接确认数据包,告诉服务端连接建立成功。

进行程序开发的同学,无论Web前端开发、Web后端开发,还是搜索引擎和大数据,几乎所有的开发领域都会涉及到网络编程。

我们知道网络协议是一个分层的协议族,也就是是有一组协议构成,从下往上各自负责各自的功能。

协议的字面意思是共同计议,商议。

这套接口通常可以参数的调整支持多种协议,包括TCP、UDP和IP等等。

网络编程为了便于理解,本文先从具体的内容开始,也就是通过一个实例介绍一下网络编程是怎么回事。

我们知道在网络通信中无论是BS架构还是CS架构,通常分为服务端和客户端,只不过BS架构中的浏览器就是客户端。

因此,本文的示例也包含服务端和客户端2部分的代码。

图1 客户端服务端通信模型这个代码清单是服务端的代码,这段代码的作用就是在服务端的某个端口建立,并等待客户端建立连接。

#!/usr/bin/env python3#-*- coding:utf-8 -*-from socket import *from time import ctimehost = ''port = 12345buffsize = 2048ADDR = (host,port)# 创建一个基于TCP协议的套接字tctime = socket(AF_INET,SOCK_STREAM)tctime.bind(ADDR)# 在指定的地址和端口tctime.listen(3)while True:print('Wait for connection ...') tctimeClient,addr = tctime.accept() print("Connection from :",addr) while True: data = tctimeClient.recv(buffsize).decode() if not data: break tctimeClient.send(('[%s] %s' % (ctime(),data)).encode()) tctimeClient.close()tctimeClient.close()阅读服务端的代码可以看出主要包括,socket、bind、listen、accept、recv和send几个。

其中值得关注的是listen和accept,两者分别用于端口和接受客户端的连接请求。

下面代码清单是客户端的实现,这里特别的地方是有一个connect函数,该函数实现与服务端建立连接。

服务端程序建立对某个端口的,等待客户端的连接请求。

客户端向服务端发送连接请求,不出意外的情况下连接建立成功,这时客户端和服务端之前就可以互发数据了。

当然,在实际生产环境中意外是经常的,因此从协议和接口层面,需要处理各种意外,本文在协议部分将详细介绍。

另外,本文实现了一个基本的客户端和服务端通信的程序,这个模式的通信在实际生产中几乎不再使用。

在实际生产中为了提高数据传输和处理的效率,通常采用异步模式,这些内容超出了本文的介绍范围,后续文章会逐渐介绍。

TCP协议详解前文说了网络协议是网络中不同计算机信息通信的语言,为了实现交互,这个语言就需要有一定的格式。

TCP协议是一个可靠的传输协议,其可靠性表现在2方面,一方面是保证数据包可以按照发送的顺序到达,另外一方面是保证数据包一定程度的正确性(后文详解为什么是一定程度上的正确性)。

其可靠性的实现则基于2点技术,一点是具有一个CRC校验,这样如果数据包中的某些数据出现错误可以通过该校验和发现;另外一点是每个数据包都有一个序号,这样就能保证数据包的顺序性,如果出现错位的数据包可以请求重发。

既然说到了格式,那我们先看一下TCP数据包的数据格式。

如下图是TCP数据包的格式,包括原端口、目的端口、和标识位等等内容,内容有些多,看着可能有点眼花。

但从大的方面理解,这个数据包其实只包含2部分内容,一个是包头,另外一个则是具体需要传输的数据。

在TCP协议的控制逻辑中,包头起着最为关键的作用,它是TCP协议中诸如建立连接、断开连接、重传和错误校验等各种特性的基础。

图2 TCP数据包格式包头的其它信息的含义都比较明了,本文仅仅介绍几个标志位(URG、ACK、PSH、RST、SYN和FIN)的含义。

这里的连接并不是物理连接,物理连接基于底层的协议已经建立完成,而且TCP建立连接也是要假设底层连接已经成功,TCP的连接其实是一个虚拟的,逻辑的连接。

简单粗暴的理解,就是客户端和服务端分别记录了各自接受到的数据包的序号,并且将自身设置为某种状态。

在TCP协议中,连接的建立通常成为3次握手,从字面的概念可以看出,连接的建立需要经过3次确认的过程。

图3 建立连接的3次握手TCP协议3次握手的过程如图所示,初始状态客户端和服务端都处于关闭状态。

主要过程分为3步:客户端发送预连接数据包: TCP的连接是由客户端主动发起建立,客户端会发送一个数据包(报文)给服务端,需要注意的是数据包中的SYN标识位为1。

我们前文已经介绍,如果SYN为1,则说明为建立连接的数据包。

同时,在该数据包中包含一个请求,该也是建立连接的依据。

服务端回复连接确认: 服务端确认可以建立连接(服务端不一定可以建立连接,因为系统中套接字的数量是有限的)的情况下会向客户端发送一个应答数据包。

同时,在应答数据包中会设置请求和应答的值,具体参考图3.客户端回复连接确认: 最后,客户端再次发送一个连接确认数据包,告诉服务端连接建立成功。

从上面流程可以看出,连接的建立需要经过多次交互,这就是我们日常中所说的建立连接是高成本的操作。

在实际生产环境中,为了应对这个问题,会减少连接建立的频度,通常的做法是建立连接池,传输数据时直接从连接池中获取连接,而不是新建连接。

有人可能觉得可以对建立连接的过程进行优化,比如将客户端最后一次的确认取消掉,觉得这个没有卵用。

因为网络拓扑是非常复杂的,特别是在广域网中,有着数不清的网络节点,因此会出现各种异常情况。

因此,TCP协议在设计的时候必须要保证异常情况下的可靠性。

我们这里举一个例子,就是连接请求超时的情况。

之后,前一个数据包经过长途跋涉最终还是到了服务端,服务端也向客户端发送了回复数据包,服务端认为连接是建立成功的,并且会维持连接。

但客户端层面认为连接是超时的,因此将永远不会关闭该连接。

这样就会造成服务端有残留的资源,从而造成服务端资源浪费,久而久之可能会导致服务端无新连接资源可用。

另外一个需要说明的是客户端和服务端的套接字都有相应的状态,而且状态会随着连接的不同阶段变化。

传输数据完成连接建立之后,客户端和服务端就可以进行数据传输了。

TCP在发送数据时都会计算整个数据包的校验和,并存储在包头的校验和字段中。

发送发计算校验和的流程大概如下:把伪首部、TCP包头和TCP数据分为16为的字,并把TCP包头中的校验和字段置0用反码加法累加所有16位数字对计算结果去反,将其填充到TCP包头的校验和字段接收方将所有原码相加,高位叠加,如果全为1则表示数据正确,否则说明数据有错误。

在数据传输中的每个请求都会有一个请求,而在接收方接收到数据后会发送一个应答,这样发送方就能知道数据是否被正确接收,而接收方也能知道数据是否出现乱序,从而保证数据包的顺序性。

连接的关闭不一定是在客户端发起,服务端也可以发起关闭连接。

关闭连接的过程如下:发起方发送一个FIN置位的数据包,用来请求关闭发送方到接收方的连接接收方发送一个应答,ACK标志位为1,确认关闭。

此时完成了发起方到接收方的连接,也即发送方无法再向接收方发送数据,但接收方还可以向发送方发送数据。

接收方数据传输完成后向发起方发送一个FIN为1的包,表示请求断开连接发起方回复一个ACK包,确认关闭成功图4 关闭连接流程示意图TCP是全双工通信,因此关闭连接时需要双向关闭连接。

首先是关闭发起方关闭本端的连接,然后是关闭接收方在收到发起方的关闭请求后,除了回复关闭应答外,还要确保数据传输完成后发起一个关闭连接的请求,保证双向同时关闭。

截止到这里,本文介绍了基于TCP协议进行网络编程的主要内容。

当然这个只是入门级的,如果需要真正理解TCP协议和网络编程还需要学习很多内容。


以上是文章"

同时,在应答数据包中会设置请求和应答的值

"的内容,欢迎阅读网控科技网的其它文章