listen:
建立监听,能否建立需要accept函数去进行检查
def listen(self, backlog: int) #backlog指定最多允许多少个客户连接到服务器。它的值至少为1。收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求。
注意:backlog应该理解为阻塞队列的长度,总共与服务器连接的客户端一共有 backlog + 1 个。阻塞队列FIFO,当连接客户端结束后阻塞队列里的第一个客服端与服务器连接成功。
accept:
def accept(self): """accept() ->(套接字对象,地址信息) 等待传入连接。返回一个新的套接字 表示连接和客户端的地址。 对于IP套接字,地址信息是一对(hostaddr, port)。 """
accept()接受一个客户端的连接请求,并返回一个新的套接字,不同于server端的socket()返回用于监听和接受客户端的连接请求的套接字;与客户端通信是通过这个新的套接字上发送和接收数据来完成的。每个连接进来的客户端,都会通过accept函数返回一个不同的客户端的socket对象和属于客户端的套接字
测试:假设服务端永久开启,listen设置有允许有1个用户端在等待,同时启动三个用户端:
启动第1个用户端,程序正常运行
启动第2个用户端,程序正常运行,但是在listen当中排队等待第一个用户端的断开
启动第3个用户端,次用户端报错:onnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
import socket sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen(1) while True: conn,addr = sk.accept() while True: ret = conn.recv(1024).decode('utf-8') print(ret) if ret == 'bye': conn.send(b'bye') break msg = input('>>') conn.send(msg.encode('utf-8')) conn.close() sk.close()
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) while True: info = input('>>') sk.send(info.encode('utf-8')) ret = sk.recv(1024).decode('utf-8') print(ret) if ret == 'bye': sk.send(b'bye') break sk.close()
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) while True: info = input('>>') sk.send(info.encode('utf-8')) ret = sk.recv(1024).decode('utf-8') print(ret) if ret == 'bye': sk.send(b'bye') break sk.close()
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) while True: info = input('>>') sk.send(info.encode('utf-8')) ret = sk.recv(1024).decode('utf-8') print(ret) if ret == 'bye': sk.send(b'bye') break sk.close()
测试2,启动用户端1,2后,关闭用户端1或2,再启动用户端3,用户端3不会报错
总结:
listen的socket对象比喻为火车站
accept的socket对象理解需要接待的旅客
如果要接到旅客,首先要到火车站等待(即listen监听的socket对象)
旅客是否到达,需要在入口处检查有没有等待的旅客(即accept在检查是否有新连接产生的socket对象),
如果超过火车站限制人数(listen限制队列数量),该发送请求的用户端报错,只能等待正在连接的用户端断开才能成功进入队列等待