TCP
TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。TCP通信需要经过创建连接、数据传送、终止连接三个步骤。
TCP的特点
- 面向连接,可以间接验证ip地址的有效性
- 应答机制: 对方收到消息,底层会回复
- 超时重传:对方收到数据没有回复那么会再次给对方发送数据,如果对方一直不回复那么会认为对方掉线
- 错误校验: 比如接收的数据的序号和发送时候的数据序号不一致,那么tcp会对数据包进行自动排序, 如果收到重复的数据包会删除
- 流量控制: 对方发送大量数据如果接收方网卡缓存区达到一定上限,那么就不让对方发送数据,等接收方把数据处理完以后再发送,保证电脑接收数据不会卡死
TCP和UDP的区别
- tcp面向连接, udp不面向连接
- tcp可靠的传输协议,udp 不可靠
- tcp 应答机制, udp没有
- tcp 超时重传,udp没有
- tcp 流量控制, udp没有
- tcp 错误校验, udp没有
- udp 适合做广播, tcp不适合
- udp传输速度比tcp传输速度要快, udp占用的资源要比tcp的占用资源要少
- udp 每次发送的数据包不能太大,上限是64k, tcp理论上没有限制 —扩展
- tcp适合文件的上传和下载,绝大多数应用都是使用tcp的
- udp 适合音视频(qq,微信)的传输,还有飞秋上线广播
TCP的创建
TCP客户端创建步骤: socket = socket.socket(AF_INIT, SOCK_STREAM) --> socket.connect(( 'ip地址' , port)) --> socket.send() --> socket.recv() --> socket.close()
TCP服务端创建步骤: socket = socket.socket(AF_INIT, SOCK_STREAM) --> socket.bind(( '' , port))绑定端口 --> socket.listen(最大等待连接数):设置监听 --> client_socket, ip_port = socket.accept() : 返回一个服务于客户端的套接字和已连接的客户端的 ip_pport --> client_socket.recv(最大字节数):接收客户端的消息 --> client_socket.send() : 回复客户端 --> client_socket.close() : 断开与客户端的连接 --> socket.close() : 关闭服务端,不再接收客户端连接请求
快速释放端口号的方法 : socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
TCP注意点
- TCP服务器一般情况下都需要绑定,否则客户端找不到这个服务器。
- TCP客户端一般不绑定,因为是主动连接服务器,所以只要确定好服务器的ip, port等信息
- CP服务器中通过listen可以将socket创建出来的主动套接字变为被动,这是服务器必须做的
- TCP客户端需要连接服务器时,需要使用connect进行连接
- 当一个客户端连接服务器时,服务器端会有一个新的套接字,用来标记该客户端,单独服务。
三次握手
- 在客户端向服务端申请连接时产生,此时,客户端会发将YSN标志位置为1,并随即发送一个seq = J 的数据。这是第一次握手
- 服务端收到客户端的申请后,将ACK,YSN标志位置为1,并将该客户端的发送的数据+1,即ack = J + 1,并随即回复一个数据seq = K,将以上数据一起返回给客户端,表示我接收到了连接请求,我也要和你建立连接了。 这是第二次握手
- 客户端接收到以上数据后,先检查客户端是否同意即ACK是否为1,并检查客户端返回的ack是否为一开始发送的报文数据+1 ,若全部符合,则客户端将ACK置为1,并回复ack = K+1,服务端确认无误后开始进行连接。 这是第三次握手
四次挥手
- 在客户端与服务端断开连接的时候产生,客户端要断开连接时,发送一个标志位FIN表示我要和你断开连接了。 第一次挥手
- 服务端接收到了客户端的FIN的数据后,返回一个ACK,确认序号为收到的序号+1。表示我收到了你的断开请求,但我需要先将剩余任务完成后才能断开。 第二次挥手
- 服务端任务完成后,会发送一个FIN给客户端,表示和客户端说,我要和你断开连接了 第三次挥手
- 客户端接收到后,会回复一个ACK,确认序号为 收到的序号+1,表示收到服务端断开连接的信息,并确认。 第四次挥手 **:在回复服务端之后,客户端会等待1~2分钟,确定服务端收到消息后,再释放端口