UDP协议通讯不安全,把传输内容传给他人后就不管了,今天讲个安全的:TCP协议。
一、TCP概述
1、概念
TCP: 面向连接的通信协议
这是一个面向连接的协议,也就是说,在收发数据之前必须和对方建立可靠的连接,一个TCP连接必须要经过三次“握手”才能建立起来,再经过四次‘挥手’结束。
2、三次‘握手’
建立连接:三次握手
看图了解一下这个过程:
- 第一次握手:主机甲向主机乙发送连接请求数据包“我可以给你发数据吗”
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、四次‘挥手’
断开连接:四次挥手
再看个图理解一下:
- 第一次挥手:当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:开始监听,等待客户端连接
客户端实例:
(5)accept():响应客户端的请求
阻塞当前线程
如果没有计算机连接,一直等待
如果有计算机连接,响应客户端
服务端实例:
先运行服务端,在运行客户端:结果
客户端:
服务端:
3、改进一下,让程序不会在一收一发后停止
客户端:
服务端:
三、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服务端都会在服务器是创建一个“线程”或者“进 程” 专门负责处理当前客户端的所有请求。
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类就能自动获得并发处理请求的能力。该模块本身就直接提供了这种类。
服务端代码:
客户端代码(客户端还是使用socket)
如果想实现不终止,可以在服务端代码的handle方法中加入死循环while True