UDP协议通讯不安全,把传输内容传给他人后就不管了,今天讲个安全的:TCP协议。

 

一、TCP概述

1、概念

TCP: 面向连接的通信协议

这是一个面向连接的协议,也就是说,在收发数据之前必须和对方建立可靠的连接,一个TCP连接必须要经过三次“握手”才能建立起来,再经过四次‘挥手’结束。

 

2、三次‘握手’

建立连接:三次握手

看图了解一下这个过程:

python三次握手WS不是256 python tcp三次握手_客户端

  • 第一次握手:主机甲向主机乙发送连接请求数据包“我可以给你发数据吗”

Client端调用connect函数,系统为Client随机分配一个端口,连同传入connect中的参数(Server的IP和端口),这就形成了一个连接四元组,客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1。

connect调用让Client端的socket处于SYN_SENT状态,等待服务器确认;

SYN:同步序列编号(Synchronize Sequence Numbers)。  

  • 第二次握手:主机乙向主机甲发送同意连接和要求同步(同步就是两台数据同时收发,协调工作)“可以,你什么时候发”

服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 

  • 第三次握手:主机甲再次向主机乙发出一个数据包确认主机乙的同步   “哥们现在就发了,你接着啊”

客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户器和服务器进入ESTABLISHED状态,完成三次握手。连接已经可以进行读写操作。

 

 

3、四次‘挥手’

断开连接:四次挥手

再看个图理解一下:

python三次握手WS不是256 python tcp三次握手_客户端_02

  • 第一次挥手:当client想要关闭它与server之间的连接。client(某个应用进程)首先调用close主动关闭连接,这时TCP发送一个FIN;client端处于FIN_WAIT1状态。 

 

  • 第二次挥手:当server端接收到FIN之后,执行被动关闭。对这个FIN进行确认,返回给client ACK。

当server端返回给client ACK后,client处于FIN_WAIT2状态,server处于CLOSE_WAIT状态。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据; 

  • 第三次挥手:一段时间之后,当server端检测到client端的关闭操作(read返回为0)。接收到文件结束符的sever端调用close关闭它的socket。这导致server端的TCP也发送一个FIN;此时server的状态为LAST_ACK。 

 

  • 第四次挥手:当client收到来自server的FIN后 。 client端的套接字处于TIME_WAIT状态,它会向server端再发送一个ack确认,此时server端收到ack确认后,此套接字处于CLOSED状态。这样每个方向上都有一个FIN和ACK。

 

 

4、存在的意义:

TCP协议适用于对速度要求相对较低,而准确性要求很高的场合。

例如:文件传输、电子邮件等等

需要建立连接,数据传输、断开连接三个步骤。

 

 

 

 

二、TCP编程

1、创建流程概述

(1)socket创建一个套接字,上次说了SOCK_DGRAM是用在UDP上的,而SOCK_STREAM是用于TCP协议的。

(2)bind绑定IP和port

(3)listen使套接字变为可以被动链接

(4)accept等待客户端的链接

(5)close关闭资源

 

2、socket模块常用于TCP的方法

(1)connect(address):连接远程计算机

(2)send():发送数据

(3)recv():接收数据
(4)listen:开始监听,等待客户端连接

 

客户端实例:

python三次握手WS不是256 python tcp三次握手_python三次握手WS不是256_03

 

(5)accept():响应客户端的请求

阻塞当前线程

如果没有计算机连接,一直等待

如果有计算机连接,响应客户端

 

服务端实例:

python三次握手WS不是256 python tcp三次握手_TCP_04

 

先运行服务端,在运行客户端:结果

客户端:

python三次握手WS不是256 python tcp三次握手_python三次握手WS不是256_05

服务端:

python三次握手WS不是256 python tcp三次握手_TCP_06

 

3、改进一下,让程序不会在一收一发后停止

客户端:

python三次握手WS不是256 python tcp三次握手_TCP_07

服务端:

python三次握手WS不是256 python tcp三次握手_TCP_08

 

三、TCP特点

  • 稳定:保证数据接收
  • 相对udp慢一些
  • web服务器一般使用TCP

 

四、套接字

socket创建出来的套接字是主动套接字

listen能够把主动套接字转化为被动套接字

 

 

五、TCP和UDP的区别

  • 基于连接与无连接
  • 对系统资源的要求(TCP较多,UDP较少)
  • UDP程序结构较简单                   
  • 流模式与数据报模式
  • TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证

 

六、SocketServer

在python中有一个单独的类专门把服务器进行了封装,方便直接调用并使用,这个类就是SocketServer

 

1、SocketServer是socket的再封装

每个客户端连接服务器时,SocketServer会在服务器上创建一线程或者进程,专门负责处理客户端

Socketserver 是在socket的基础上python编写的用于编写web服务的基础框架

SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进 程” 专门负责处理当前客户端的所有请求。

python三次握手WS不是256 python tcp三次握手_客户端_09

2、SocketServer中类分为三种类型

一是Server类:BaseServer/TCPServer/UDPServer用来接收客户的请求。TCPServer处理TCP请求,UDPServer处理UDP请求。BaserServer是基类,不能直接使用。TCPServer继承自BaseServer,UDPServer继承自TCPServer。暂时不明白为什么UDPServer要继承自TCPServer,后面再说。

 

二是Handler类:BaseRequestHandler/DatagramRequestHandler/StreamRequestHandler用来处理每一个客户请求。一般用使用BaseRequestHandler就行,但StreamRequestHandler/DatagramRequestHandler提供了一些特别的功能,前者用来处理流式(TCP)请求,后者处理数据报(UDP)请求。Server每收到一个客户请求就会创建一个Handler类示例来处理该请求。默认情况下,TCPServer/UDPServer是单进程单线程的模型,依次处理每个客户请求,一个请求处理完毕才能接着处理下一个请求。

 

三是MixIn类:ForkingMixIn/ThreadingMixIn用来为Server提供多进程/多线程并发处理能力的。ForkingMixIn是多进程模型,ThreadingMixin是多线程模型。这里特别巧妙的是,你只要创建一个类,同时继承Server类和MixIn类就能自动获得并发处理请求的能力。该模块本身就直接提供了这种类。

 

服务端代码:

python三次握手WS不是256 python tcp三次握手_python三次握手WS不是256_10

客户端代码(客户端还是使用socket)

python三次握手WS不是256 python tcp三次握手_TCP_11

如果想实现不终止,可以在服务端代码的handle方法中加入死循环while True