'''
=>IO阻塞 :就是普通的sk.accept接收不到数据就一直等待
=>IO非阻塞 sk.setblocking(False) #设置服务器的accept, recv均为非阻塞
=> IO多路复用
比如socketserver,多个客户端连接,单线程下实现并发效果,就叫多路复用。
---------------------------------------------------------------------------
通过一个select()系统调用来监视多个文件描述符的数组
can_read, can_write, _ = select.select(inputs, outputs, None, None)
第一个参数是我们需要监听可读的套接字, 第二个参数是我们需要监听可写的套接字,
第三个参数使我们需要监听异常的套接字, 第四个则是时间限制设置.
如果监听的套接字满足了可读可写条件, 那么所返回的can,read 或是 can_write就会有值了,
然后我们就可以利用这些返回值进行随后的操作了。
----------------------------------------------------------------------------
'''
--------------------------------------------------------------------------------------------------------------------------------------
IOservices类
import socket
import select
sk = socket.socket()
print("首次创建sk对象---》",sk)
sk.bind(("127.0.0.1",5656))
sk.listen(5)
sk_conn = [sk]
#创建select监听sk对象
while True:
readsk,writesk,errorsk = select.select(sk_conn,[],[],5)
# print("这是获取到的readsk:--》",readsk) #获取不到客户端的连接信息就会一直获取/
for read in readsk: #执行一次后第二次再执行时sk是空列表[],所以或执行conn对象
if read == sk:
conn,addre = read.accept() #建立接收是本地sk的事情,之后的信息接收发送是客户端conn对象的事情
sk_conn.append(conn)
# print("conn第一次:----》",conn)
else:
try:
data = read.recv(1024)
print("来自%s客户消息:" % (sk_conn.index(read)), data.decode('utf8'))
send_inp = input("回复%s客户:" % (sk_conn.index(read)))
read.sendall(bytes(send_inp, 'utf8'))
except Exception as e:
sk_conn.remove(read) #这里是处理客户端直接关闭后清除客户端的连接对象
IOclient 类
import socket
sk = socket.socket()
sk.connect(("127.0.0.1",5656))
while True:
print(sk)
inp = input("我是客户端:")
try:
sk.sendall(bytes(inp,'utf8'))
data = sk.recv(1024)
print(data.decode('utf8'))
except Exception as e: #这里判断服务端关闭后给出提示
print("服务已关闭",e)
break