1、简单 echo server
import socket
import selectors
selec = selectors.DefaultSelector()
print(selec)
server = socket.socket()
server.bind(('127.0.0.1', 9999))
server.listen()
server.setblocking(False)
def accept(conn:socket.socket, mask:int):
conn, raddr = server.accept()
conn.setblocking(False)
key = selec.register(conn, selectors.EVENT_READ, recv)
print(key)
print('conn', conn)
print('raddr', raddr)
def recv(conn:socket.socket, mask:int):
data = conn.recv(1024)
print(data)
msg = 'Your msg = {} from {}'.format(data.decode(), conn.getpeername()).encode()
print(msg.decode())
conn.send(msg)
key = selec.register(server, selectors.EVENT_READ, accept)
print(key)
print(type(key))
print(key.__class__.mro())
while True:
events = selec.select()
print(events)
for key, mask in events:
print(type(key), type(mask))
print(key.data)
key.data(key.fileobj, mask)
server.close()
selec.close()
<selectors.SelectSelector object at 0x000001EA3F596F10>
SelectorKey(fileobj=<socket.socket fd=388, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=388, events=1, data=<function accept at 0x000001EA3F3BD280>)
<class 'selectors.SelectorKey'>
[<class 'selectors.SelectorKey'>, <class 'tuple'>, <class 'object'>]
[(SelectorKey(fileobj=<socket.socket fd=388, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=388, events=1, data=<function accept at 0x000001EA3F3BD280>), 1)]
<class 'selectors.SelectorKey'> <class 'int'>
<function accept at 0x000001EA3F3BD280>
SelectorKey(fileobj=<socket.socket fd=384, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63364)>, fd=384, events=1, data=<function recv at 0x000001EA3F73DAF0>)
conn <socket.socket fd=384, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63364)>
raddr ('127.0.0.1', 63364)
[(SelectorKey(fileobj=<socket.socket fd=388, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=388, events=1, data=<function accept at 0x000001EA3F3BD280>), 1)]
<class 'selectors.SelectorKey'> <class 'int'>
<function accept at 0x000001EA3F3BD280>
SelectorKey(fileobj=<socket.socket fd=360, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63367)>, fd=360, events=1, data=<function recv at 0x000001EA3F73DAF0>)
conn <socket.socket fd=360, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63367)>
raddr ('127.0.0.1', 63367)
[(SelectorKey(fileobj=<socket.socket fd=388, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=388, events=1, data=<function accept at 0x000001EA3F3BD280>), 1)]
<class 'selectors.SelectorKey'> <class 'int'>
<function accept at 0x000001EA3F3BD280>
SelectorKey(fileobj=<socket.socket fd=356, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63369)>, fd=356, events=1, data=<function recv at 0x000001EA3F73DAF0>)
conn <socket.socket fd=356, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63369)>
raddr ('127.0.0.1', 63369)
[(SelectorKey(fileobj=<socket.socket fd=384, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63364)>, fd=384, events=1, data=<function recv at 0x000001EA3F73DAF0>), 1)]
<class 'selectors.SelectorKey'> <class 'int'>
<function recv at 0x000001EA3F73DAF0>
b'123456789'
Your msg = 123456789 from ('127.0.0.1', 63364)
[(SelectorKey(fileobj=<socket.socket fd=360, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63367)>, fd=360, events=1, data=<function recv at 0x000001EA3F73DAF0>), 1)]
<class 'selectors.SelectorKey'> <class 'int'>
<function recv at 0x000001EA3F73DAF0>
b'123456789'
Your msg = 123456789 from ('127.0.0.1', 63367)
[(SelectorKey(fileobj=<socket.socket fd=360, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63367)>, fd=360, events=1, data=<function recv at 0x000001EA3F73DAF0>), 1)]
<class 'selectors.SelectorKey'> <class 'int'>
<function recv at 0x000001EA3F73DAF0>
b'123456789'
Your msg = 123456789 from ('127.0.0.1', 63367)
2、优化 echo server
import selectors
import socket
import logging
FORMAT = "%(asctime)s %(threadName)10s %(thread)8d %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)
selector = selectors.DefaultSelector()
sock = socket.socket()
sock.bind(('127.0.0.1', 9999))
sock.listen()
logging.info(sock)
sock.setblocking(False)
def accept(sock:socket.socket, mask:int):
logging.info('start in accept function ~~~~~')
conn, raddr = sock.accept()
conn.setblocking(False)
logging.info('New clinet socket [{}] is in accepting.'.format(conn))
key = selector.register(conn, selectors.EVENT_READ, read)
logging.info(key)
logging.info('end in accept function ~~~~~')
def read(conn:socket.socket, mask:int):
logging.info('start in read function ~~~~~')
data = conn.recv(1024)
msg = "Your msg = {} ~~~~~~~~~~~".format(data.decode())
logging.info(msg)
conn.send(msg.encode())
logging.info('end in read function~~~~~')
key = selector.register(sock, selectors.EVENT_READ, accept)
logging.info(key)
while True:
events = selector.select()
print('events ===>', events)
for key, mask in events:
key.data(key.fileobj, mask)
2022-04-30 18:49:22,158 MainThread 2640 <socket.socket fd=372, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>
2022-04-30 18:49:22,159 MainThread 2640 SelectorKey(fileobj=<socket.socket fd=372, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=372, events=1, data=<function accept at 0x000002680D0878B0>)
events ===> [(SelectorKey(fileobj=<socket.socket fd=372, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=372, events=1, data=<function accept at 0x000002680D0878B0>), 1)]
2022-04-30 18:49:28,834 MainThread 2640 start in accept function ~~~~~
2022-04-30 18:49:28,834 MainThread 2640 New clinet socket [<socket.socket fd=400, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60145)>] is in accepting.
2022-04-30 18:49:28,834 MainThread 2640 SelectorKey(fileobj=<socket.socket fd=400, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60145)>, fd=400, events=1, data=<function read at 0x000002680D276C10>)
2022-04-30 18:49:28,834 MainThread 2640 end in accept function ~~~~~
events ===> [(SelectorKey(fileobj=<socket.socket fd=400, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60145)>, fd=400, events=1, data=<function read at 0x000002680D276C10>), 1)]
2022-04-30 18:49:38,068 MainThread 2640 start in read function ~~~~~
2022-04-30 18:49:38,068 MainThread 2640 Your msg = 60145 ~~~~~~~~~~~
2022-04-30 18:49:38,068 MainThread 2640 end in read function~~~~~
2022-04-30 18:50:04,452 MainThread 2640 start in accept function ~~~~~
2022-04-30 18:50:04,452 MainThread 2640 New clinet socket [<socket.socket fd=404, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60160)>] is in accepting.
2022-04-30 18:50:04,452 MainThread 2640 SelectorKey(fileobj=<socket.socket fd=404, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60160)>, fd=404, events=1, data=<function read at 0x000002680D276C10>)
2022-04-30 18:50:04,452 MainThread 2640 end in accept function ~~~~~
events ===> [(SelectorKey(fileobj=<socket.socket fd=372, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=372, events=1, data=<function accept at 0x000002680D0878B0>), 1)]
2022-04-30 18:50:12,404 MainThread 2640 start in read function ~~~~~
2022-04-30 18:50:12,404 MainThread 2640 Your msg = 60160 ~~~~~~~~~~~
2022-04-30 18:50:12,404 MainThread 2640 end in read function~~~~~
events ===> [(SelectorKey(fileobj=<socket.socket fd=404, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60160)>, fd=404, events=1, data=<function read at 0x000002680D276C10>), 1)]
2022-04-30 18:50:18,101 MainThread 2640 start in accept function ~~~~~
2022-04-30 18:50:18,102 MainThread 2640 New clinet socket [<socket.socket fd=364, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60171)>] is in accepting.
2022-04-30 18:50:18,102 MainThread 2640 SelectorKey(fileobj=<socket.socket fd=364, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60171)>, fd=364, events=1, data=<function read at 0x000002680D276C10>)
2022-04-30 18:50:18,102 MainThread 2640 end in accept function ~~~~~
events ===> [(SelectorKey(fileobj=<socket.socket fd=372, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=372, events=1, data=<function accept at 0x000002680D0878B0>), 1)]
events ===> [(SelectorKey(fileobj=<socket.socket fd=364, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 60171)>, fd=364, events=1, data=<function read at 0x000002680D276C10>), 1)]
2022-04-30 18:50:27,282 MainThread 2640 start in read function ~~~~~
2022-04-30 18:50:27,282 MainThread 2640 Your msg = 60171 ~~~~~~~~~~~
2022-04-30 18:50:27,282 MainThread 2640 end in read function~~~~~
3、群聊 server
import selectors
import threading
import socket
import logging
import time
FORMAT = "%(asctime)s %(threadName)10s %(thread)8d %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)
class ChatServer:
def __init__(self, ip='127.0.0.1', port=9999):
self.sock = socket.socket()
self.addr = ip, port
self.event = threading.Event()
self.selector = selectors.DefaultSelector()
def start(self):
self.sock.bind(self.addr)
self.sock.listen()
self.sock.setblocking(False)
self.selector.register(self.sock, selectors.EVENT_READ, self.accept)
threading.Thread(target=self.select, name='select', daemon=True).start()
def select(self):
while not self.event.is_set():
events = self.selector.select()
print('events ===>', events)
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
def accept(self, sock:socket.socket, mask:int):
conn, raddr = sock.accept()
conn.setblocking(False)
logging.info('new client socket {} is in accept.'.format(conn))
key = self.selector.register(conn, selectors.EVENT_READ, self.recv)
logging.info(key)
def recv(self, conn:socket.socket, mask:int):
data = conn.recv(1024).strip()
if data == 'quit' or data == b'':
self.selector.unregister(conn)
conn.close()
return
msg = "Your msg = {} ~~~~~~".format(data.decode()).encode()
logging.info(msg)
for key in self.selector.get_map().values():
print(list(self.selector.get_map()))
print(self.recv)
print(key.data)
print(self.recv is key.data)
print(self.recv == key.data)
if key.data == self.recv:
key.fileobj.send(msg)
def stop(self):
self.event.is_set()
fobjs = []
for fd, key in self.selector.get_map().items():
fobjs.append(key.fileobj)
for fobj in fobjs:
self.selector.unregister(fobj)
fobj.close()
self.selector.close()
if __name__ == '__main__':
cs = ChatServer()
cs.start()
while True:
cmd = input('>>>>>>>').strip()
if cmd == 'quit':
logging.info('Quit.')
cs.stop()
break
print(threading.enumerate())
>>>>>>>events ===> [(SelectorKey(fileobj=<socket.socket fd=344, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=344, events=1, data=<bound method ChatServer.accept of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
2022-04-30 22:53:41,564 select 34804 new client socket <socket.socket fd=412, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63182)> is in accept.
2022-04-30 22:53:41,564 select 34804 SelectorKey(fileobj=<socket.socket fd=412, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63182)>, fd=412, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>)
events ===> [(SelectorKey(fileobj=<socket.socket fd=344, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=344, events=1, data=<bound method ChatServer.accept of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
2022-04-30 22:54:35,294 select 34804 new client socket <socket.socket fd=416, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63187)> is in accept.
2022-04-30 22:54:35,294 select 34804 SelectorKey(fileobj=<socket.socket fd=416, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63187)>, fd=416, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>)
events ===> [(SelectorKey(fileobj=<socket.socket fd=344, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>, fd=344, events=1, data=<bound method ChatServer.accept of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
2022-04-30 22:54:44,573 select 34804 new client socket <socket.socket fd=420, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63188)> is in accept.
2022-04-30 22:54:44,573 select 34804 SelectorKey(fileobj=<socket.socket fd=420, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63188)>, fd=420, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>)
2022-04-30 22:54:56,836 select 34804 b'Your msg = 63188 ~~~~~~'
events ===> [(SelectorKey(fileobj=<socket.socket fd=420, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63188)>, fd=420, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.accept of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
False
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
2022-04-30 22:55:16,936 select 34804 b'Your msg = 63187 ~~~~~~'
events ===> [(SelectorKey(fileobj=<socket.socket fd=416, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63187)>, fd=416, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.accept of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
False
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
events ===> [(SelectorKey(fileobj=<socket.socket fd=412, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63182)>, fd=412, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.accept of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
False
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
[344, 412, 416, 420]
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>
False
True
2022-04-30 22:55:23,834 select 34804 b'Your msg = 63182 ~~~~~~'
events ===> [(SelectorKey(fileobj=<socket.socket fd=412, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63182)>, fd=412, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
events ===> [(SelectorKey(fileobj=<socket.socket fd=416, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63187)>, fd=416, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
events ===> [(SelectorKey(fileobj=<socket.socket fd=420, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 63188)>, fd=420, events=1, data=<bound method ChatServer.recv of <__main__.ChatServer object at 0x000002E16B3AB0A0>>), 1)]
[<_MainThread(MainThread, started 11656)>, <Thread(select, started daemon 34804)>]
>>>>>>>quit
events ===>2022-04-30 22:55:41,392 MainThread 11656 Quit.
Process finished with exit code 0
|