server.py
#! /usr/bin/evn python3
# coding:utf-8
import types
import socket
import selectors
sel = selectors.DefaultSelector()
def accept_wrapper(sock):
conn, addr = sock.accept()
print("accepted connection from", addr)
conn.setblocking(False)
event_mask = selectors.EVENT_READ | selectors.EVENT_WRITE
data = types.SimpleNamespace(addr=addr, inb=b'', outb=b'')
sel.register(conn, event_mask, data)
def service_connection(key, mask):
sock, data = key.fileobj, key.data
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024)
if recv_data:
data.outb += recv_data
else:
print("closing connection to", data.addr)
sel.unregister(sock)
sock.close()
if mask & selectors.EVENT_WRITE:
if data.outb:
print('echoing', repr(data.outb), 'to', data.addr)
sent = sock.send(data.outb)
data.outb = data.outb[sent:]
addr = ('127.0.0.1', 8888)
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind(addr)
lsock.listen()
print("listen on", addr)
lsock.setblocking(False)
sel.register(lsock, selectors.EVENT_READ, data=None)
while True:
event = sel.select(timeout=None)
# 遍历就绪的socket
# key包含socket和data,mask是事件掩码
for key, mask in event:
if key.data is None:
accept_wrapper(key.fileobj)
else:
service_connection(key, mask)
client.py
#! /usr/bin/env python3
# coding:utf-8
import selectors
import socket, types
sel = selectors.DefaultSelector()
for i in range(3):
sock = socket.socket()
sock.setblocking(False)
sock.connect_ex(('127.0.0.1', 8888))
event_mask = selectors.EVENT_READ | selectors.EVENT_WRITE
data = types.SimpleNamespace(
id=i,
outb=b'i am a superman',
recv_total=0,
inb=b''
)
sel.register(sock, event_mask, data)
while True:
try:
events = sel.select(timeout=None)
except OSError:
print("OSError")
break
for key, mask in events:
sock, data = key.fileobj, key.data
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024)
if recv_data:
print("received", repr(recv_data), "from connection", data.id)
data.recv_total += len(recv_data)
if not recv_data or data.recv_total == 15:
print("closing connect", data.id)
sel.unregister(sock)
sock.close()
if mask & selectors.EVENT_WRITE:
if data.outb:
print("sending", repr(data.outb), "to connection", data.id)
data_len = sock.send(data.outb)
data.outb = data.outb[data_len:]