TCP(Transmission Control Protocol) 传输控制协议。是一种面向连接的、可靠的、基于字节流的传输层通信协议。
SYN(synchronous 建立联机)
ACK(acknowledgement 确认)
PSH(push 传送)
FIN(finish 结束)
RST(reset 重置)
URG(urgent 紧急)
Sequence number(顺序号码)
Acknowledge number(确认号码)
establish 建立,创建
三次握手(Three-Way Handshake)即建立 TCP 连接,是指建立一个 TCP连接时,需要客户端和服务端总共发送 3 个包以确认连接的建立。在 socket 编程中,这一过程由客户端执行 connect 来触发,
#客户端代码
#客户端首先发起请求连接服务器
import socket
host = '127.0.0.1'#设置ip
port = 8088 #端口
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))#连接服务端,三次握手触发
整个流程以及函数调用如下图所示:
大致流程如下:
• 客户端向服务器发送一个SYN J
• 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
• 客户端再想服务器发一个确认ACK K+1
从图中可以看出: 当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。
总结:
客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。
所谓四次挥手(Four-Way Wavehand)即终止 TCP 连接,就是指断开一个 TCP连接时,需要客户端和服务端总共发送 4 个包以确认连接的断开。在 socket 编程中,这一过程由客户端或服务端任一方执行 close 来触发,
#服务器端代码
import socket
host = '127.0.0.1'#设置ip
port = 8088 #端口
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#连接服务端
s.bind((host,port))
s.listen(5)
print("服务端已开启,等待客户端连接...")
conn, addr = s.accept()#连接
print("客户端已连接...\n")
因为这里没有服务器端和客户端互相发送东西,所以你们看不出来close()的作用。我也没有写。想要具体了解close()方法时,看我写的【socket建立TCP连接】这篇文章,我将功能2,改为close()功能了,当先建立连接后,如果先按2关闭了,再按1聊天的话,就会报错报错。OSError: [WinError 10038] 在一个非套接字上尝试了一个操作。
因为收发是建立再连接之上的
图示过程如下:
• 某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;
• 另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
• 一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;
• 接收到这个FIN的源发送端TCP对它进行确认。
这样每个方向上都有一个FIN和ACK。
上面是一方主动关闭,另一方被动关闭的情况,实际中还会出现
同时发起主动关闭的情况,具体流程如下图:
(1)三次握手是什么或者流程?四次握手呢?答案前面分析就是。
(2)为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
这是因为服务端在 LISTEN 状态下,收到建立连接请求的 SYN 报文后,把 ACK和 SYN 放在一个报文里发送给客户端。而关闭连接时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据, 己方也未必全部数据都发送给对方了,所以己方可以立即 close,也可以发送一些数据给对方后,再发送FIN 报文给对方来表示同意现在关闭连接,因此,己方 ACK 和 FIN 一般都会分开发送。
举个例子: A 和 B 打电话,通话即将结束后,A 说“我没啥要说的了”,B回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,这样通话才算结束。
(3)为什么要三次握手?
三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常。
第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己接收正常,对方发送正常
第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送接收正常
所以三次握手就能确认双发收发功能都正常,缺一不可。
(4)为什么要传回SYN?
接收端传回发送端所发送的 SYN 是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。
SYN 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement[汉译:确认字符 ,在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误。 ])消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。
(5)传了 SYN,为啥还要传 ACK?
双方通信无误必须是两者互相发送信息都无误。传了 SYN,证明发送方(主动关闭方)到接收方(被动关闭方)的通道没有问题,但是接收方到发送方的通道还需要 ACK 信号来进行验证。
参考链接:美团面试题
注意: 如果socket TCP连接这种报错,可以换个端口试试。
OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。
谢谢支持!