一、UDP实现简单聊天室

分为server端和client端

server.py:

【笔记】python网络编程_python

client.py

【笔记】python网络编程_python_02


二、TCP三次握手

(1)序号(sequence number):Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

(2)确认号(acknowledgement number):Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。

(3)标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等



【笔记】python网络编程_python_03


1、发送端发送SYN=1,序号seq=x,此时进入SYN-SEND状态

2、接收端收到后,返回标志位SYN=1,ACK=1,表示序号有效,并发送自己的seq=y和确认号Ack=x+1,此时接收端进入SYN-RCVD状态

3、发送到收到数据后进行校验Ack的值,正确后将其作为自己的seq的值,并返回标志位ACK=1,并发送确认号Ack=y+1,此时进入ESTABLISHED状态

4、接收端收到后进行Ack值校验,确认无误后也进入ESTABLISHED状态

为什么要三次握手呢,两次不行么?

我们来想想如果只有两次,第一次握手后服务器就ESTABLISHED了,再第二次握手的时候,服务器返回客户端的数据因为一些原因没有发送到客户端,客户端超时机制就关闭了,而服务器一直开着造成了资源的浪费。“第三次握手”是客户端向服务器端发送数据,这个数据就是要告诉服务器,客户端有没有收到服务器“第二次握手”时传过去的数据。若发送的这个数据是“收到了”的信息,接收后服务器就正常建立TCP连接,否则建立TCP连接失败,服务器关闭连接端口。由此减少服务器开销和接收到失效请求发生的错误。


三、TCP四次挥手

【笔记】python网络编程_python_04

1、客户端发送标志位FIN=1请求释放连接,序号seq=u,此时状态为FIN_WAIT_1

2、服务器收到客户端是数据,发送标志位ACK=1,确认号Ack=u+1和自己的序号seq=v,此时进入半关闭CLOSE_WAIT状态

3、客户端收到后进行Ack校验,无误后进入FIN_WAIT_2状态

4、服务器做好准备释放连接了,就再发送标志位FIN=1,ACK=1,确认号Ack=u+1和自己的序号seq=w,此时进入LAST_ACK状态

5、客户端收到后进行Ack校验,无误后发送标志位ACK=1,确认号Ack=w+1,进入TIME_WAIT状态(注意此时不是直接关闭,等待一段时间后自动关闭)

6、服务器收到客户端的数据并进行校验无误后,进入close状态

为什么最后客户端不能立即关闭?

是为了避免最后一次握手的时候服务器没有收到客户端的数据,还可以请求重新发送。如果服务端收到了直接关闭了,客户端一直没有收到服务器要求请求重发的请求的话,再关闭。


四、TCP的socket实现

server.py

【笔记】python网络编程_python_05

client.py

【笔记】python网络编程_python_06