def selector(): sel = DefaultSelector() sel.register(proc.stdout, EVENT_READ, 0) sel.register(proc.stderr, EVENT_READ, 1) while True: for key, mask in sel.select(): yield key.data, decode(key.fileobj.readline(linesize))
def select(self, timeout): # There are tasks to be scheduled. Continue simulating. if timeout is None: # If timeout is infinity, just wait without increasing _current_time. return DefaultSelector.select(self, timeout) self._current_time += timeout return DefaultSelector.select(self, 0)
def run_until_complete(task): tasks = [(task, None)] selector = DefaultSelector() while tasks or selector.get_map(): timeout = 0 if tasks else None if selector.get_map(): for key, events in selector.select(timeout): tasks.append((key.data, None)) selector.unregister(key.fileobj) queue, tasks = tasks, [] for task, data in queue: try: data = task.send(data) except StopIteration: pass else: if data and data[0] == EVENT_READ: selector.register(data[1], EVENT_READ, task) elif data and data[0] == EVENT_WRITE: selector.register(data[1], EVENT_WRITE, task) elif data and data[0] == 'spawn': tasks.append((data[1], None)) tasks.append((task, data[1])) else: tasks.append((task, None))
class TorSocketLoop(threading.Thread): def __init__(self, our_sock, send_func): super().__init__(name='SocketLoop{:x}'.format(our_sock.fileno())) self._our_sock = our_sock self._send_func = send_func self._do_loop = True self._cntrl_r, self._cntrl_w = socket.socketpair() self._selector = DefaultSelector() self._selector.register(self._our_sock, EVENT_READ, self._do_recv) self._selector.register(self._cntrl_r, EVENT_READ, self._do_stop) def _do_recv(self, sock): try: data = sock.recv(1024) self._send_func(data) except ConnectionResetError: logger.debug('Client was badly disconnected...') def _do_stop(self, sock): self._do_loop = False def _cleanup(self): self._selector.unregister(self._cntrl_r) self._cntrl_w.close() self._cntrl_r.close() self.close_sock() self._selector.close() @property def fileno(self): if not self._our_sock: return None return self._our_sock.fileno() def close_sock(self): if not self._our_sock: return self._selector.unregister(self._our_sock) # self._our_sock.shutdown(socket.SHUT_WR) self._our_sock.close() self._our_sock = None def stop(self): self._cntrl_w.send(b'\1') def run(self): logger.debug('Starting...') while self._do_loop: events = self._selector.select() for key, _ in events: callback = key.data callback(key.fileobj) self._cleanup() logger.debug('Stopped...') def append(self, data): self._our_sock.send(data)
class Loop: def __init__(self): self.ready = deque() self.selector = DefaultSelector() self.futures = {} def create_task(self, task): self.ready.append(task) def run_forever(self): while True: while not self.ready: completed_futures = [future for future in self.futures if not future.running()] for future in completed_futures: self.ready.append(self.futures.pop(future)) # so select() is blocking. If set a negative time out it won't block. events = self.selector.select(-1) # add these socket events and unregister them from listened to: for key, _ in events: self.ready.append(key.data) # add the task to the ready queue self.selector.unregister(key.fileobj) while self.ready: self.current_task = self.ready.popleft() # try to run current_task... try: # run task to next yield point reason, what = self.current_task.send(None) # reason, what = self.current_task.send(None) if reason == 'waiting_to_accept': self.selector.register(what, EVENT_READ, self.current_task) elif reason == 'waiting_to_read': self.selector.register(what, EVENT_READ, self.current_task) elif reason == 'waiting_to_write': self.selector.register(what, EVENT_WRITE, self.current_task) elif reason == 'waiting_for_future': self.futures[what] = self.current_task else: raise RuntimeError( 'Something bad happened... er. reason={}'.format(reason)) except StopIteration: pass async def sock_recv(self, sock, maxbytes): # wait to read from the socket await read_wait(sock) return sock.recv(maxbytes) async def sock_accept(self, sock): # wait to read/hear from the socket await accept_wait(sock) return sock.accept() async def sock_sendall(self, sock, data): while data: # wait to be able to write to the socket await write_wait(sock) nsent = sock.send(data) data = data[nsent:] def run_in_executor(self, executor, func, *args): return executor.submit(func, *args)
def run_until_complete(task): tasks = [(task, None)] selector = DefaultSelector() while tasks or selector.get_map(): print("___________________________________") # poll I/O and resume when ready timeout = 0.0 if tasks else None for key, events in selector.select(timeout): tasks.append((key.data, None)) selector.unregister(key.fileobj) queue, tasks = tasks, [] for task, data in queue: try: print(f"loop: send {data} into {task.__name__}") data = task.send(data) print(f"loop: received {data} from {task.__name__}") except StopIteration as res: pass except Exception as exp: print(repr(exp)) else: if data: req, _ = data if req == EVENT_READ: stream = data[1] selector.register(stream, EVENT_READ, task) elif req == EVENT_WRITE: stream = data[1] selector.register(data[1], EVENT_WRITE, task) else: tasks.append((task, None))
def wait(gen: PQGen[RV], timeout: Optional[float] = None) -> RV: """ Wait for a generator using the best option available on the platform. :param gen: a generator performing database operations and yielding (fd, `Ready`) pairs when it would block. :param timeout: timeout (in seconds) to check for other interrupt, e.g. to allow Ctrl-C. :type timeout: float :return: whatever *gen* returns on completion. """ sel = DefaultSelector() try: fd, s = next(gen) while 1: sel.register(fd, s) ready = None while not ready: ready = sel.select(timeout=timeout) sel.unregister(fd) assert len(ready) == 1 fd, s = gen.send(ready[0][1]) except StopIteration as ex: rv: RV = ex.args[0] if ex.args else None return rv
class Loop: def __init__(self): self.sel = DefaultSelector() self.queue = deque() def create_task(self, coro): sock = coro.send(None) self.sel.register(sock, EVENT_WRITE, coro) self.queue.append(coro) def run(self): while self.queue: events = self.sel.select() for key, _ in events: coro = key.data event = key.events file_obj = key.fileobj self.sel.unregister(file_obj) try: if event == EVENT_WRITE: self.sel.register(file_obj, EVENT_READ, coro) elif event == EVENT_READ: self.sel.register(file_obj, EVENT_WRITE, coro) coro.send(None) except StopIteration: self.queue.popleft() except: pass else: return
class Spider: def __init__(self): self.selector = DefaultSelector() self.urls = [] self.stop = False self.headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36", "Connection": "close", } def creat_loop(self): while not self.stop: ready = self.selector.select() for key, mask in ready: call_back = key.data call_back(key) @timer def main(self): for index in range(10): url = 'http://shop.projectsedu.com/goods/{}/'.format(index) self.urls.append(url) feture = Fecher(self) feture.get(url) self.creat_loop()
def wait_selector(gen: PQGen[RV], fileno: int, timeout: Optional[float] = None) -> RV: """ Wait for a generator using the best strategy available. :param gen: a generator performing database operations and yielding `Ready` values when it would block. :param fileno: the file descriptor to wait on. :param timeout: timeout (in seconds) to check for other interrupt, e.g. to allow Ctrl-C. :type timeout: float :return: whatever *gen* returns on completion. Consume *gen*, scheduling `fileno` for completion when it is reported to block. Once ready again send the ready state back to *gen*. """ try: s = next(gen) sel = DefaultSelector() while 1: sel.register(fileno, s) ready = None while not ready: ready = sel.select(timeout=timeout) sel.unregister(fileno) s = gen.send(ready[0][1]) except StopIteration as ex: rv: RV = ex.args[0] if ex.args else None return rv
def proxy_process_encoded(sock1, sock2): """在两个sockek之间转发数据:任何一个收到的,编码后转发到另一个""" sel = DefaultSelector() sel.register(sock1, EVENT_READ) sel.register(sock2, EVENT_READ) while True: events = sel.select() for (key, ev) in events: try: data_in = key.fileobj.recv(8192) except ConnectionResetError as e: print(key.fileobj, "\nreset receive!") sock1.close() sock2.close() return if data_in: if key.fileobj == sock1: sock2.send(xor_encode(data_in)) else: sock1.send(xor_encode(data_in)) else: sock1.close() sock2.close() return
class Loop(object): def __init__(self): self.svr = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.svr.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.svr.setblocking(False) self.svr.bind(('0.0.0.0', 5230)) self.svr.listen(1000) self.selector = DefaultSelector() self.selector.register(self.svr, EVENT_READ, self.on_accept) def on_accept(self, s): try: conn, addr = s.accept() except IOError as e: error = Tools.get_error_code(str(e)) if error == ErrorCode.WSAEINTR or error == ErrorCode.EWOULDBLOCK: pass else: raise IOError(str(e)) proxy = Proxy(conn) proxy.engine.core = proxy.core() next(proxy.engine.core) # self.selector.register(self.conn, EVENT_READ, self.on_read) #print(conn.fileno(), addr) def run(self): while True: events = self.selector.select(2) for key, mask in events: callback = key.data callback(key.fileobj)
def wait_conn(gen: PQGenConn[RV], timeout: Optional[float] = None) -> RV: """ Wait for a connection generator using the best strategy available. :param gen: a generator performing database operations and yielding (fd, `Ready`) pairs when it would block. :param timeout: timeout (in seconds) to check for other interrupt, e.g. to allow Ctrl-C. :type timeout: float :return: whatever *gen* returns on completion. Behave like in `wait()`, but take the fileno to wait from the generator itself, which might change during processing. """ try: fileno, s = next(gen) sel = DefaultSelector() while 1: sel.register(fileno, s) ready = None while not ready: ready = sel.select(timeout=timeout) sel.unregister(fileno) fileno, s = gen.send(ready[0][1]) except StopIteration as ex: rv: RV = ex.args[0] if ex.args else None return rv
def run_until_complete(task): tasks = [(task, None)] # NEW: prepare for I/O multiplexing. selector = DefaultSelector() # NEW: watch out, all tasks might be suspended at the same time. while tasks or selector.get_map(): # NEW: poll I/O operation status and resume tasks when ready. timeout = 0.0 if tasks else None for key, events in selector.select(timeout): tasks.append((key.data, None)) selector.unregister(key.fileobj) queue, tasks = tasks, [] for task, data in queue: try: data = task.send(data) except StopIteration: pass else: # NEW: register for I/O and suspend the task. if data and data[0] == EVENT_READ: selector.register(data[1], EVENT_READ, task) elif data and data[0] == EVENT_WRITE: selector.register(data[1], EVENT_WRITE, task) else: tasks.append((task, None))
def _receive(self): """ Continuously read data from the socket and put it on the receive queue. """ selector = DefaultSelector() selector.register(self.socket, EVENT_READ) getLogger(__name__).debug("Receive thread starting.") while self.active: try: val = selector.select(self.SELECT_TIMEOUT_INTERVAL) if val: with self.socket_lock: header = None # protecting against close error if self.socket is not None: header = self.socket.recv(self.HEADER_SIZE) if header and header is not None: data = self._read_data(header) self.receive_queue.put(data) else: # connection closed from other end self.controller.disconnect() except Exception as err: getLogger(__name__).warning(("Unexpected exception occurred," " receive thread may be in a corrupted state\n" "Error: {}".format(err))) getLogger(__name__).debug("Receive thread done.")
def wait( gen: Union[PQGen[RV], PQGenConn[RV]], timeout: Optional[float] = None ) -> RV: """ Wait for a generator using the best option available on the platform. :param gen: a generator performing database operations and yielding (fd, `Ready`) pairs when it would block. :param timeout: timeout (in seconds) to check for other interrupt, e.g. to allow Ctrl-C. :type timeout: float :return: whatever *gen* returns on completion. """ fd: int s: Wait sel = DefaultSelector() try: # Use the first generated item to tell if it's a PQgen or PQgenConn. # Note: mypy gets confused by the behaviour of this generator. item = next(gen) if isinstance(item, tuple): fd, s = item while 1: sel.register(fd, s) ready = None while not ready: ready = sel.select(timeout=timeout) sel.unregister(fd) assert len(ready) == 1 fd, s = gen.send(ready[0][1]) else: fd = item # type: ignore[assignment] s = next(gen) # type: ignore[assignment] while 1: sel.register(fd, s) ready = None while not ready: ready = sel.select(timeout=timeout) sel.unregister(fd) assert len(ready) == 1 s = gen.send(ready[0][1]) # type: ignore[arg-type,assignment] except StopIteration as ex: rv: RV = ex.args[0] if ex.args else None return rv
def selector(): sel = DefaultSelector() sel.register(proc.stdout, EVENT_READ, 0) sel.register(proc.stderr, EVENT_READ, 1) while True: ready = sel.select(line_timeout) if not ready and line_timeout: raise ProcessLineTimedOut("popen line timeout expired", getattr(proc, "argv", None), getattr(proc, "machine", None)) for key, mask in ready: yield key.data, decode(key.fileobj.readline(linesize))
def main(): selector = DefaultSelector() selector.register(sys.stdin, EVENT_READ) last_hello = 0 while True: for event, mask in selector.select(0.1): process_input(event.fileobj) if time() - last_hello > 3: last_hello = time() print_hello()
def selector(): sel = DefaultSelector() sel.register(proc.stdout.channel, EVENT_READ) while True: ready = sel.select(line_timeout) if not ready and line_timeout: raise ProcessLineTimedOut("popen line timeout expired", getattr(proc, "argv", None), getattr(proc, "machine", None)) for key, mask in ready: yield
class Loop: def __init__(self): self.ready = deque() self.selector = DefaultSelector() async def sock_recv(self, sock, maxbytes): await read_wait(sock) return sock.recv(maxbytes) async def sock_accept(self, sock): await read_wait(sock) return sock.accept() #old version """ async def sock_sendall(self, sock, data): while data: await write_wait(sock) nsent = sock.send(data) data = data[nsent:] """ #speed up version async def sock_sendall(self, sock, data): while data: try: nsent = sock.send(data) data = data[nsent:] except BlockingIOError: await write_wait(sock) def create_task(self, coro): self.ready.append(coro) def run_forever(self): while True: while not self.ready: events = self.selector.select() for key, _ in events: self.ready.append(key.data) self.selector.unregister(key.fileobj) while self.ready: self.current_task = self.ready.popleft() try: op, *args = self.current_task.send(None) getattr(self, op)(*args) except StopIteration: pass def read_wait(self, sock): self.selector.register(sock, EVENT_READ, self.current_task) def write_wait(self, sock): self.selector.register(sock, EVENT_WRITE, self.current_task)
class IRC(Service): DEFAULT_PORT = 6667 TIMEOUT = 3 def __init__(self,events): super().__init__(events,'irc') self.servers = set() self.selector = DefaultSelector() self.events = events self.has_servers = Event() self.channels = {}#server:[channels] def respond(self,addr,command): if command['action']=='connect': server = command['host'] nick = command['nick'] port = command.get('port',self.DEFAULT_PORT) self.connect((server,port),nick) if command['action']=='status': print(self.servers) self.broadcast({ 'kind':'status', 'status':{ 'servers':{ s: { 'channels':v } for s,v in self.channels.items() } } }) def connect(self,addr,nick): host = addr[0] if host not in self.servers: print(nick) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print(addr) sock.connect(addr) self.events.listen(host,self.check_channels) self.selector.register(sock,EVENT_READ|EVENT_WRITE,ChatServerInterface(addr[0],nick,self.events)) self.servers.add(host) self.channels[host] = list() if not self.has_servers.is_set(): self.has_servers.set() def check_channels(self,addr,event): if event['kind']=='irc': if event['command']=='332': print(event['event'],event['arguments']) self.channels[event['event']].append(event['arguments'][1].lower()) def loop(self): while True: self.has_servers.wait() for key,mask in self.selector.select(): if mask&EVENT_READ==EVENT_READ: key.data.read_data(key.fileobj) if mask&EVENT_WRITE==EVENT_WRITE: key.data.write_data(key.fileobj)
class Server(object): def __init__(self): self.address = ('127.0.0.1', 8080) self.selector = DefaultSelector() self.decoder = DecoderHandler() self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def start(self): self.server.bind(self.address) self.server.listen(50) self.server.setblocking(False) # 注册ACCEPT事件 和 回调函数 self.selector.register(self.server.fileno(), EVENT_READ, (self.connected, self.server)) self.loop() # 处理ACCEPT事件 def connected(self, key, mask): client, addr = key.data[1].accept( ) # client, addr = self.server.accept() print('接收客户端{}连接...'.format(addr)) client.setblocking(False) # 注册读事件 和 回调函数 # 只要读缓冲区中有数据那么就会触发读事件 即便一次性没有读取完数据 那么也会继续触发读事件 [水平触发] self.selector.register(client.fileno(), EVENT_READ, (self.read, client)) def read(self, key, mask): if mask & EVENT_READ: # 读事件 pass if mask & EVENT_WRITE: # 写事件 pass client = key.data[1] data = client.recv(1024) self.decoder.decode(data) self.send(key, '\r\nHello, World\r\n') def send(self, key, msg): client = key.data[1] # print('发送数据...') # 返回发送成功的字节数 d = client.send(str(msg).encode()) # print(d) # 事件循环 def loop(self): while True: # print('执行select...') data = self.selector.select() # timeout 单位秒 for key, mask in data: callback = key.data[0] callback(key, mask)
class Loop: def __init__(self): # queue of ready tasks self.ready = deque() # interface for the operating system's `select` calls, # informing which file handles (sockets) are ready to read/write self.selector = DefaultSelector() async def sock_recv(self, sock, maxbytes): await read_wait(sock) return sock.recv(maxbytes) async def sock_accept(self, sock): await read_wait(sock) return sock.accept() async def sock_sendall(self, sock, data): while data: try: nsent = sock.send(data) data = data[nsent:] except BlockingIOError: await write_wait(sock) def create_task(self, coro): self.ready.append(coro) def run_forever(self): while True: while not self.ready: events = self.selector.select() for key, _ in events: self.ready.append(key.data) self.selector.unregister(key.fileobj) while self.ready: self.current_task = self.ready.popleft() try: op, *args = self.current_task.send( None) # Run to the yield # call the operation yielded by the pending task getattr(self, op)(*args) except StopIteration: pass def read_wait(self, sock): # The current_tasks expects a signal that the socket `sock` is readable self.selector.register(sock, EVENT_READ, self.current_task) def write_wait(self, sock): self.selector.register(sock, EVENT_WRITE, self.current_task)
class EventLoop: def __init__(self, server_id, handler: Handler): self.select = DefaultSelector() self.server_id = server_id self.handler = handler def register(self, fd: Socket, events: SelectorKey, data=None): fd.setblocking(False) self.select.register(fd, events, data) def modify(self, fd: Socket, events: SelectorKey, data=None): self.select.modify(fd, events, data) def unregister(self, fd): self.select.unregister(fd) def run(self): self.register(self.server_id, selectors.EVENT_READ) while True: events = self.select.select() for key, mask in events: if mask == EVENT_READ: if key.fileobj == self.server_id: self.accept(key.fileobj) else: self.read(key.fileobj) elif mask == EVENT_WRITE: print(f"EventLoop, key={key}, data={key.data}") self.write(key.fileobj, key.data) def accept(self, sock): """sock 要处理的 fd, mask 为事件类型 READ or WRITE""" conn = self.handler.accept(sock) # Should be ready self.register(conn, EVENT_READ, self.read) def read(self, conn): for data in self.handler.read(conn): if data and data not in ('q', 'Q'): resp = self.handler.handle(conn, data) self.modify(conn, EVENT_WRITE, resp) else: self.unregister(conn) self.handler.close(conn) def write(self, conn, data): self.handler.send(conn, data) self.modify(conn, EVENT_READ) def close(self): self.select.close()
class Loop: def __init__(self): self.ready = deque() self.selector = DefaultSelector() async def sock_recv(self, sock, maxbytes): # wait for something to happen await read_wait(sock) return sock.recv(maxbytes) async def sock_accept(self, sock): # wait for something to happen await read_wait(sock) return sock.accept() async def sock_sendall(self, sock, data): while data: await write_wait(sock) nsent = sock.send(data) data = data[nsent:] def create_task(self, coro): self.ready.append(coro) def run_forever(self): while True: while not self.ready: # if there's not nothing to ready to run, go get all IO events = self.selector.select() for key, _ in events: self.ready.append(key.data) self.selector.unregister(key.fileobj) while self.ready: self.current_task = self.ready.popleft() try: op, *args = self.current_task.send( None) # Run to the yield getattr(self, op)(*args) # Sneaky method except StopIteration: pass def read_wait(self, sock): # the current task is interested in reading on that socket self.selector.register(sock, EVENT_READ, self.current_task) def write_wait(self, sock): # the current task is intertested in writing on that socket self.selector.register(sock, EVENT_WRITE, self.current_task)
def loop(): pre_loop_barrier.wait(1) selector = DefaultSelector() selector.register(sig_r_fd, EVENT_READ) with suppress(StopIteration): while True: events = selector.select(timeout=5) if len(events) == 0: raise StopIteration for key, mask in events: if key.fd == sig_r_fd: data = os.read(sig_r_fd, 4) self._sigchld_caught = True raise StopIteration self._post_loop_barrier.wait(1)
def handle(self): record_bytes = read_tls_record(self.rfile) record = TLS(record_bytes) ext_server_name = record.getlayer(TLS_Ext_ServerName) if ext_server_name == None: self.log_message("ServerName is missing from TLS record") return server_names = [ str(s.servername, "ascii") for s in ext_server_name.servernames ] self.log_message(f"Server names: {server_names}") if len(server_names) == 0: self.log_message("List of server names is empty") return host = server_names[0] s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, 443)) s.send(record_bytes) def read_client(): s.send(read_tls_record(self.rfile)) def read_remote(): self.wfile.write(read_tls_record(s)) sel = DefaultSelector() sel.register(self.rfile, EVENT_READ, read_client) sel.register(s, EVENT_READ, read_remote) got_read_error = False while not got_read_error: events = sel.select() for key, mask in events: try: key.data() except ReadError: got_read_error = True break s.close()
def main(): addr_components = os.environ.get('ADDR', DEFAULT_ADDR).split(':') addr = addr_components[0], int(addr_components[1]) msgs = [bytes(msg, ENCODING) for msg in sys.stdin] payload = b''.join(msgs) sel = DefaultSelector() with socket(AF_INET, SOCK_STREAM) as sock: sock.connect(addr) sock.setblocking(False) data = SimpleNamespace(buf=payload, proceed=True) sel.register(sock, EVENT_READ | EVENT_WRITE, data) while data.proceed: for key, mask in sel.select(timeout=POLL_INTERVAL): if mask & EVENT_READ: handle_read(sock, data) if mask & EVENT_WRITE: handle_write(sock, data)
class TorSocketLoop(threading.Thread): def __init__(self, our_sock, send_func): super().__init__(name='SocketLoop{:x}'.format(our_sock.fileno())) self._our_sock = our_sock self._send_func = send_func self._do_loop = True self._cntrl_r, self._cntrl_w = socket.socketpair() self._selector = DefaultSelector() self._selector.register(self._our_sock, EVENT_READ, self._do_recv) self._selector.register(self._cntrl_r, EVENT_READ, self._do_stop) def _do_recv(self, sock): data = sock.recv(1024) self._send_func(data) def _do_stop(self, sock): self._do_loop = False def _cleanup(self): self._selector.unregister(self._cntrl_r) self._cntrl_w.close() self._cntrl_r.close() self._selector.unregister(self._our_sock) self._our_sock.shutdown(socket.SHUT_WR) self._our_sock.close() self._selector.close() def stop(self): self._cntrl_w.send(b'\1') def run(self): logger.debug("Starting...") while self._do_loop: events = self._selector.select() for key, _ in events: callback = key.data callback(key.fileobj) self._cleanup() logger.debug("Stopped...") def append(self, data): self._our_sock.send(data)
class Loop: def __init__(self): self.ready = deque() self.selector = DefaultSelector() async def sock_recv(self, sock, maxbytes): await read_wait(sock) return sock.recv(maxbytes) async def sock_accept(self, sock): await read_wait(sock) return sock.accept() async def sock_sendall(self, sock, data): while data: try: nsent = sock.send(data) data = data[nsent:] except BlockingIOError: await write_wait(sock) def create_task(self, coro): self.ready.append(coro) def run_forever(self): while True: while not self.ready: events = self.selector.select() for key, _ in events: self.ready.append(key.data) self.selector.unregister(key.fileobj) while self.ready: self.current_task = self.ready.popleft() try: op, *args = self.current_task.send(None) getattr(self, op)(*args) except StopIteration: pass def read_wait(self, sock): self.selector.register(sock, EVENT_READ, self.current_task) def write_wait(self, sock): self.selector.register(sock, EVENT_WRITE, self.current_task)
class Selector: def __init__(self): self._sel = DefaultSelector() self._fds = {} def register_read(self, task, fileno): return self._register(task, fileno, EVENT_READ) def register_write(self, task, fileno): return self._register(task, fileno, EVENT_WRITE) def _unregister(self, fd): fileno = fd.fileno() if fileno in self._fds: LOG.debug('unregister fd %r', fd) del self._fds[fileno] self._sel.unregister(fileno) def _register(self, task, fileno, events): fd = self._fds.get(fileno, None) if fd is None: fd = KernelFd(self, fileno, task) self._fds[fileno] = fd if fd.task is not task: raise RuntimeError( 'file descriptor already registered by other task') if fd.selector_key is None: LOG.debug('register fd %r, events=%r', fd, events) fd.selector_key = self._sel.register(fd, events) elif fd.events != events: LOG.debug('modify fd %r, events=%r', fd, events) fd.selector_key = self._sel.modify(fd, events) return fd def poll(self, timeout): io_events = self._sel.select(timeout=timeout) for key, mask in io_events: fd = key.fileobj if fd.task.is_alive and fd.events & mask: LOG.debug('task %r wakeup by fd %r', fd.task, fd) yield fd.task def close(self): self._sel.close()
def proxy_process_encoded(sock1, sock2): """在两个sockek之间转发数据:任何一个收到的,编码后转发到另一个""" sel = DefaultSelector() sel.register(sock1, EVENT_READ) sel.register(sock2, EVENT_READ) while True: events = sel.select() for (key, ev) in events: data_in = key.fileobj.recv(8192) if data_in: if key.fileobj == sock1: sock2.send(xor_encode(data_in)) else: sock1.send(xor_encode(data_in)) else: sock1.close() sock2.close() return
class Loop: def __init__(self): self.ready = deque() self.selector = DefaultSelector() def create_task(self, task): self.ready.append(task) def run_forever(self): while True: # hmmn, nothing to run -> must be waiting on stuff... while not self.ready: events = self.selector.select() # add these events and unregister them from listened to: for key, _ in events: self.ready.append(key.data) self.selector.unregister(key.fileobj) while self.ready: self.current_task = self.ready.popleft() # try to run current_task... try: # run task to next yield point reason, sock = next(self.current_task) if reason == 'waiting_to_accept': self.selector.register(sock, EVENT_READ, self.current_task) elif reason == 'waiting_to_read': self.selector.register(sock, EVENT_READ, self.current_task) elif reason == 'waiting_to_write': self.selector.register(sock, EVENT_WRITE, self.current_task) else: raise RuntimeError('Something bad happened... er. reason={}'.format(reason)) except StopIteration: pass def sock_recv(self, sock, maxbytes): # wait to read from the socket return sock.recv(maxbytes) def sock_accept(self, sock): # wait to read/hear from the socket return sock.accept() def sock_sendall(self, sock, data): while data: # wait to be able to write to the socket nsent = sock.send(data) data = data[nsent:]
def loop(self): arrow_buttons = InputDevice('/dev/input/event0') control_buttons = InputDevice('/dev/input/event1') selector = DefaultSelector() selector.register(arrow_buttons, EVENT_READ) selector.register(control_buttons, EVENT_READ) while True: for key, mask in selector.select(): device = key.fileobj for event in device.read(): if event.type != ecodes.EV_KEY: continue event_cat = categorize(event) if event_cat.keystate != 0: continue try: self.send_command(self.COMMAND_MAP[event_cat.keycode]) except KeyError: pass
class Loop: def __init__(self): self.ready = deque() self.selectors = DefaultSelector() # a way to watch socket IO async def sock_recv(self, sock, maxbytes): await read_wait(sock) # wait for something happen return sock.recv(maxbytes) async def sock_accept(self, sock): await read_wait(sock) return sock.sock_accept() async def sock_sendall(self, sock, data): while data : try: nsent = sock.send(data) data = data[nsent:] # send partial data except BlockingIOError: await write_wait(sock) def create_task(self, coro): self.ready.append(coro) def run_forever(self): while True: while not self.ready: events = self.selectors.select() for key, _ in events: self.ready.append(key.data) self.selectors.unregister(key.fileobj) while self.ready: self.current_task = self.ready.popleft() try: op, *args = self.current_task.send(None) # run to the yield getattr(self,op)(*args) # Sneaky method call except StopIteration: pass def read_wait(self, sock): self.selectors.register(sock, EVENT_READ, self.current_task) def write_wait(self, sock): self.selectors.register
class MySocket: def get_conn(self): self.sel = DefaultSelector() self.host_port = ('0.0.0.0', 45633) self.ss = socket.socket() self.ss.setblocking(False) self.ss.bind(self.host_port) self.ss.listen(10) self.sel.register(self.ss.fileno(), EVENT_READ, self.get_accept) while 1: ready = self.sel.select() for key, mask in ready: print(key.data) call_back = key.data call_back(key) def get_accept(self, mask): self.sel.unregister(mask.fd) self.conn, self.addr = self.ss.accept() self.conn.setblocking(False) self.sel.register(self.conn.fileno(), EVENT_READ, self.get_recv) def get_recv(self, mask): # self.sel.unregister(mask.fd) self.data = self.conn.recv(1024) if self.data: # self.conn.send(self.data) self.sel.unregister(mask.fd) self.sel.register(self.conn.fileno(), EVENT_WRITE, self.get_send) else: self.conn.close() self.sel.unregister(mask.fd) def get_send(self, mask): self.sel.unregister(mask.fd) self.conn.send(self.data) self.sel.register(self.conn.fileno(), EVENT_READ, self.get_recv)
request_callback = lambda sock: sock.send(request.encode()) response_callback = lambda sock: \ print((sock.recv(1000)).decode().split("\n")[-1], 'finish at %s' % str(datetime.now())[:-7]) def get(): sock = socket.socket() sock.setblocking(False) try: sock.connect(('localhost', 3000)) except: pass sel.register(sock, EVENT_WRITE, lambda: request_callback(sock)) get_count = 4 print("starts at %s" % str(datetime.now())[:-7]) for i in range(get_count): get() while True: events = sel.select() for key, _ in events: callback = key.data event = key.events sel.unregister(key.fileobj) callback() if event == EVENT_WRITE: sel.register(key.fileobj, EVENT_READ, lambda: response_callback(key.fileobj)) elif event == EVENT_WRITE: sel.register(key.fileobj, EVENT_WRITE, lambda: request_callback(key.fileobj))
class EventLoop: def __init__(self): self.tasks = deque() self.selector = DefaultSelector() def run_until_complete(self, task): self.tasks.append(task) self.run() def pause(self): return "pause", None def schedule(self, target): return "schedule", target def sock_accept(self, sock): yield ("read", sock) return sock.accept() def sock_recv(self, sock): yield ("read", sock) return sock.recv(1024) def sock_sendall(self, sock, data): yield ("write", sock) return sock.sendall(data) def start_server(self, handler, host, port, backlog=0): handler = partial(handler, self) with socket.socket() as sock: sock.bind((host, port)) sock.listen(backlog) print("Listening on {}:{}".format(host, port)) while True: conn, addr = yield from self.sock_accept(sock) print("Accepted client from", addr) yield self.schedule(handler(conn)) def run(self): while self.tasks or self.selector.get_map(): for _ in range(len(self.tasks)): try: task = self.tasks.popleft() tag, value = next(task) if tag == "schedule": self.tasks.append(value) self.tasks.append(task) elif tag == "read": self.selector.register(value, EVENT_READ, data=task) elif tag == "write": self.selector.register(value, EVENT_WRITE, data=task) elif tag == "pause": self.tasks.append(task) else: raise ValueError("Incorrect tag") except StopIteration: continue if self.selector.get_map(): for key, event in self.selector.select(): if event & EVENT_READ or event & EVENT_WRITE: self.tasks.append(key.data) self.selector.unregister(key.fileobj)
class Loop: def __init__(self): self.ready = collections.deque() self.selector = DefaultSelector() async def sock_accept(self, sock): ''' Wait for the server socket to become readable, accept a new client and return her socket, addr pair. ''' await read_wait(sock) return sock.accept() async def sock_recv(self, sock, maxbytes): ''' Wait for the socket to become readable, read data from the socket and return data. ''' await read_wait(sock) return sock.recv(maxbytes) async def sock_sendall(self, sock, data): ''' While we have some data to send, wait for the socket to become writeable and send some data. ''' while data: await write_wait(sock) nbytes = sock.send(data) # Modify data according to the number of bytes sent this time data = data[nbytes:] def create_task(self, coro): self.ready.append(coro) def run_forever(self): while True: while not self.ready: events = self.selector.select() for key, _ in events: self.selector.unregister(key.fileobj) self.ready.append(key.data) while self.ready: # I need this task in another method, so I attach it here self.current_task = self.ready.popleft() try: # drive the coroutine to the next yield op, *args = self.current_task.send(None) except StopIteration: pass else: # call method on myself # this methods will register sockets with selector getattr(self, op)(*args) def read_wait(self, sock): # When this socket is ready, drive this task to the next yield self.selector.register(sock, EVENT_READ, self.current_task) def write_wait(self, sock): self.selector.register(sock, EVENT_WRITE, self.current_task)
class TCPServer: def __init__(self, port): self.port = port self.sock = None self.selector = DefaultSelector() # Advance self.listen() method. A future has been attached to the # server socket, that has been registered in selector. And a callback # has been attached to this future. Task(self.listen()) def run(self): while True: ready = self.selector.select() for key, events in ready: fut = key.data fut.resolve() def listen(self): server_sock = self._create_socket() with server_sock: try: client_sock, remote_addr = self.sock.accept() except BlockingIOError: pass fut = Future() self.selector.register(self.sock, EVENT_READ, fut) while True: yield fut Task(self.handle_client()) def handle_client(self): client_sock, remote_addr = self.sock.accept() client_sock.setblocking(False) client_name = '{} {}'.format(*client_sock.getpeername()) print('Connected', client_name) # Register client socket for reading and wait for this event fut = Future() self.selector.register(client_sock, EVENT_READ, fut) yield fut buffer = [] while True: try: chunk = client_sock.recv(1024) buffer.append(chunk) except BlockingIOError: # Yield the same future, so we don't need to register # it again. By the way, callback is the same for all # futures, so it doesn't matter in my case. yield fut continue print('Received chunk from client', client_name) if chunk.endswith(b'end'): print('Got all data from client', client_name) request = b''.join(buffer).decode('utf8') response = (request.upper() * 100).encode('utf8') self.selector.unregister(client_sock) fut = Future() self.selector.register(client_sock, EVENT_WRITE, fut) break # This future was attached to the client_sock yield fut while True: try: bytes_sent = client_sock.send(response) print(bytes_sent, 'bytes sent to client', client_name) response = response[bytes_sent:] except BlockingIOError: print('Socket blockes for', client_name) yield fut continue else: if not response: # All response sent print('Response sent to client', client_name) self.selector.unregister(client_sock) client_sock.close() break def _create_socket(self): self.sock = socket.socket() self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 10) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind(('', self.port)) self.sock.setblocking(False) self.sock.listen(10) self.responses = {} return self.sock
def selector(): sel = DefaultSelector() sel.register(proc.stdout.channel, EVENT_READ) while True: for key, mask in sel.select(): yield
class NewRemote(object): def __init__(self): self.selector = DefaultSelector() self.init_hardware() self.mouseevents = [] self.prev_value = 1 self.keynames = { 127: "menu", 28: "ok", 103: "up", 108: "down", 105: "left", 106: "right", 1: "back", 172: "home", 114: "volumedown", 115: "volumeup", 116: "power", 272: "btn_left"} def init_hardware(self): path_dir = '/dev/input/by-path/' paths = ( path_dir + 'platform-20980000.usb-usb-0:1.2:1.0-event-kbd', path_dir + 'platform-20980000.usb-usb-0:1.2:1.1-event-mouse', path_dir + 'platform-20980000.usb-usb-0:1.4:1.0-event-kbd', path_dir + 'platform-20980000.usb-usb-0:1.4:1.1-event-mouse') for path in paths: i = InputDevice(path) i.grab() self.selector.register(i,EVENT_READ) def event(self,timeout=None): for key, mask in self.selector.select(timeout=timeout): device = key.fileobj for ev in device.read(): if ev.type == ecodes.EV_REL or ev.code == ecodes.BTN_MOUSE: self.mouseevents.append(self.mouseaction(ev.type,ev.code,ev.value)) elif ev.type == ecodes.SYN_REPORT: tmp = self.mouseevents self.mouseevents = [] return "mouse", tmp elif ev.type == ecodes.EV_KEY: return self.keyaction(ev.code,ev.value) def mouseaction(self, _type, code, value): return {'type': _type, 'code': code, 'value': value} def keyaction(self, code, value): if value == 0 and self.prev_value == 0: return if value == 1: self.prev_value = 1 return if value == 2: if code == 28 or code == 272 or code == 116: self.prev_value = 2 return else: self.prev_value = 1 if self.prev_value == 2: pressmode = 'long' else: pressmode = 'single' keyname = self.keynames[code] self.prev_value = 0 return "kbd", {'keyname': keyname, 'pressmode': pressmode}
# a task get a generator # then call next to execute the first part, before yied Task(get('/?q=python+socket+&t=lm&ia=about')) Task(get('/?q=golang+socket+&t=lm&ia=about')) Task(get('/?q=rust+socket+&t=lm&ia=about')) Task(get('/?q=erlang+socket+&t=lm&ia=about')) Task(get('/?q=python+socket+&t=lm&ia=about')) Task(get('/?q=golang+socket+&t=lm&ia=about')) Task(get('/?q=rust+socket+&t=lm&ia=about')) Task(get('/?q=erlang+socket+&t=lm&ia=about')) Task(get('/?q=python+socket+&t=lm&ia=about')) Task(get('/?q=golang+socket+&t=lm&ia=about')) Task(get('/?q=rust+socket+&t=lm&ia=about')) Task(get('/?q=erlang+socket+&t=lm&ia=about')) Task(get('/?q=python+socket+&t=lm&ia=about')) Task(get('/?q=golang+socket+&t=lm&ia=about')) Task(get('/?q=rust+socket+&t=lm&ia=about')) Task(get('/?q=erlang+socket+&t=lm&ia=about')) while n_tasks: # retrieve events events = selector.select() for event, mask in events: future = event.data # retrieve the future # call the callbacks associated to the future future.resolve() # get launched serially, so final time is time for one request times number of requests print("took %.1f sec" % (time.time() - start))
class Loop: """ Событийный цикл, который использует очередь сдвухсторонним доступом Цикл опрашивает селектор на предмет готовности событий для чтения и записи в сокет """ def __init__(self): """ Конструктор событийного цикла, который хранит очередь :return: """ self.ready = deque() self.selector = DefaultSelector() async def sock_recv(self, sock, max_bytes): """ курутина для чтения данных из сокета в асинхронный способ :param sock: дескриптор сокета :param max_bytes: максимальное количество байт, который могут быть прочитаны за один раз без блокировки :return: принятые из сокета данные в банарном виде """ await read_wait(sock) return sock.recv(max_bytes) async def sock_accept(self, sock): await read_wait(sock) return sock.accept() async def sock_sendall(self, sock, data): while data: try: n_sent = sock.send(data) data = data[n_sent:] except BlockingIOError: await write_wait(sock) def create_task(self, coro): self.ready.append(coro) def run_forever(self): while True: while not self.ready: events = self.selector.select() for key, _ in events: self.ready.append(key.data) self.selector.unregister(key.fileobj) while self.ready: self.current_task = self.ready.popleft() try: # запускаем генератор до появления yield op, *args = self.current_task.send(None) getattr(self, op)(*args) except StopIteration: pass def read_wait(self, sock): self.selector.register(sock, EVENT_READ, self.current_task) def write_wait(self, sock): self.selector.register(sock, EVENT_WRITE, self.current_task)
class Main(object): def __init__(self, fb): assert isinstance(fb, Framebuffer) self._fb = fb # get all input devices devices = [InputDevice(fn) for fn in evdev.list_devices()] # filter out non key devices for device in devices.copy(): cap = device.capabilities() if ecodes.EV_KEY not in cap: devices.remove(device) continue self._selector = DefaultSelector() # This works because InputDevice has a `fileno()` method. for device in devices: self._selector.register(device, EVENT_READ) def _color565(self, r, g, b): """Convert red, green, blue components to a 16-bit 565 RGB value. Components should be values 0 to 255. """ return (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)) def _img_to_rgb565_bytes(self): pixels = [self._color565(r, g, b) for (r, g, b) in self._img.getdata()] return pack('H' * len(pixels), *pixels) def _write_image(self, img): if (1 == self._fb.bits_per_pixel): image_bytes = img.tobytes("raw", "1;IR", self._fb.line_length) else: self._img = img image_bytes = self._img_to_rgb565_bytes() self._fb.write_raw(image_bytes) def _do_countdown(self): if (1 == self._fb.bits_per_pixel): img = Image.new("1", self._fb.resolution, 1) else: img = Image.new("RGB", self._fb.resolution, 'black') fnt = ImageFont.truetype(font="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", size=96) d = ImageDraw.Draw(img) for i in range(3, 0, -1): # clear the image d.rectangle(((0, 0), self._fb.resolution), fill=1) # draw the text text_width, text_height = d.textsize(str(i), font=fnt) x = (self._fb.resolution.x - text_width) / 2 y = (self._fb.resolution.y - text_height) / 2 d.text((x, y), str(i), font=fnt) self._write_image(img) # give some time to read time.sleep(1.25) def _draw_text(self, text, size): if (1 == self._fb.bits_per_pixel): img = Image.new("1", self._fb.resolution, 1) else: img = Image.new("RGB", self._fb.resolution, 'black') fnt = ImageFont.truetype(font="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", size=size) d = ImageDraw.Draw(img) text_width, text_height = d.textsize(text, font=fnt) x = (self._fb.resolution.x - text_width) / 2 y = (self._fb.resolution.y - text_height) / 2 d.text((x, y), text, font=fnt) self._write_image(img) def _take_picture(self): args = 'fswebcam --quiet --no-banner' args += ' --scale {0}x{1}'.format(self._fb.resolution.x, self._fb.resolution.y) if self._fb.grayscale or self._fb.bits_per_pixel == 1: args += ' --greyscale' args += ' --png --save {0}'.format(self._filename) fswebcam = Popen(args, shell=True) fswebcam.wait() def _show_picture(self): if (1 == self._fb.bits_per_pixel): self._write_image(ImageMath.eval('convert(img, "1")', img=Image.open(self._filename))) else: self._write_image(img=Image.open(self._filename)) def run(self): self._draw_text('Ready!', 36) # TODO: listen for keypresses on a background thread, otherwise they pile up while taking a picture. while True: for key, mask in self._selector.select(): device = key.fileobj for event in device.read(): if event.type != ecodes.EV_KEY: # ignore non-key events continue if not event.value: # ignore key up events continue if event.code in [ecodes.KEY_ENTER, ecodes.KEY_CAMERA]: # enter button or camera button takes a picture self._do_countdown() self._draw_text('Cheese!', 36) self._filename = 'raw-{0}.png'.format(time.strftime("%Y%m%d-%H%M%S")) self._take_picture() self._draw_text('Please wait...', 24) self._show_picture() elif event.code == ecodes.KEY_BACKSPACE: # back button to exit as usual. exit(0)
class SimpleServer(object): """ This is a simple server receiving and sending utf-8 plain text lines over TCP/IP. It should use epoll or other efficient mechanisms if available to support a large number of clients without cpu hogging. All data sent to connections will be utf-8 encoded. All received lines from clients are expected to be utf-8 encoded. Lines longer than 10KB will be quietly dropped. """ def __init__(self, port, callback): logging.basicConfig(level=logging.INFO) self.clients_kept_for_sending = [] self.selector = DefaultSelector() self.callback = callback self.server_socket = socket.socket(family=socket.AF_INET6, type=socket.SOCK_STREAM) self.server_socket.bind(("::0", port)) self.server_socket.listen(5) self.selector.register(self.server_socket, EVENT_READ, data=None) self.server_socket.setblocking(False) def close(self): self.server_socket.close() def _remove_socket(self, socket): try: self.selector.unregister(socket) except KeyError: pass def _handle_new_client(self, socket, addr): client = SimpleClient(socket, self, addr) self.selector.register(socket, EVENT_READ, data=client) self.callback(client) def _mark_client_for_sending(self, client, marked): if marked: self.selector.modify(client.socket, EVENT_READ | EVENT_WRITE, data=client) else: self.selector.modify(client.socket, EVENT_READ, data=client) def tick(self, timeout=0): """ This will check for any server events and process them. If timeout is greater than zero, it will wait at most that amount of time in seconds until something happens. (This is useful if you want to save some cpu time and you have nothing else to do) For debugging purposes, it returns the amount of events processed. """ # get rid of old connections we kept around for sending: entry_removed = True while entry_removed: entry_removed = False for entry in self.clients_kept_for_sending: if entry[1] <= time.time() or len(entry[0].send_buffer) == 0: try: entry[0].close() except: pass self.clients_kept_for_sending.remove(entry) entry_removed = True # wait for socket events: events = self.selector.select(timeout=timeout) events_processed = 0 for key, mask in events: if mask & EVENT_READ != 0: events_processed = events_processed + 1 # handle accept for server socket: if key.data == None: conn, addr = self.server_socket.accept() self._handle_new_client(conn, addr) continue # handle client socket receive: key.data._do_recv() continue if mask & EVENT_WRITE != 0: events_processed = events_processed + 1 # handle client socket send: key.data._do_outstanding_send() continue logging.debugging("unknown socket event happening, bug?") return events_processed