BIO模型的缺陷在于在接收recv/发送send数据时发生阻塞,无法与别的客户端建立连接;采用多线程的方法,当开辟多个线程时耗费资源,因此可以设置socket为非阻塞状态,使用python语言为:
socket.setblocking(False)
优点:非阻塞
缺点:服务器端当 accept 一个请求后,加入 fds 集合,每次轮询一遍 fds 集合 recv (非阻塞)数据,没有数据则立即返回错误,每次轮询所有 fd (包括没有发生读写实际的 fd)会很浪费 CPU。(C10K)
python示例代码如下:
服务端:
import socket
socket = socket.socket() # 生成套接字
socket.setblocking(False) # 设置非阻塞
socket.bind(('**.*.**.**', 8000)) # 绑定
socket.listen(5) # 设置监听数量
conn_que = [] # 客户端套接字队列
while True: # 循环查询是否有客户端连接
try:
conn, addr = socket.accept() # 有连接则设置非阻塞,加入套接字队列
print(addr, '链接')
conn.setblocking(False)
conn_que.append(conn)
except Exception as e: # 无连接pass继续查询,不检测异常时会出错
pass
new_que = [i for i in conn_que] # 复制套接字队列到新列表,以免后续的删除操作错误(可以试一下队列删除操作)
for con in new_que: # 查询每个客户端的数据传输
try:
date = con.recv(1024)
if date:
print(date)
con.send(date)
else:
print('断开连接', con)
con.close()
conn_que.remove(con)
except Exception as e:
pass
客户端:
import socket
if __name__ == '__main__':
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
client.connect(('**.*.*.*', 8000))
# mes = "hello"
while True:
mes = input("发送的数据:")
client.send(mes.encode())
mes1 = client.recv(1024)
print(mes1.decode())
client.close()
运行结果: