#!/usr/bin/env python3 import sys import time import select import socket import empty import thr def close( sock ): sock.close() def conn( port, host='localhost' ): cs = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) try: cs.connect( ( host, port ) ) except: return None return cs def send( sock, s ): try: b = s.encode() sock.sendall( b ) except: return False return True def recv( sock ): while True: r = select.select( [ sock ], [], [], 1.0 ) if r[ 0 ]: break s = '' try: bufmax = 100 * 1024 b = sock.recv( bufmax ) s = b.decode() except: return None return s def recv_thr_new( sock, cb ): e = empty.new() e.quited = False def f(): s = recv( sock ) if not s: quit() return cb( s ) th = thr.loop_new( f ) def quit(): if e.quited: return e.quited = True th.quit_ev.set() close( sock ) cb( None ) th.start() def stop(): quit() th.stop() return empty.add( e, locals() ) def srv_sock_new( port ): ss = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) ss.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) ss.bind( ( '', port ) ) ss.listen( 5 ) return ss def accept( sock ): try: ( cs, adr ) = sock.accept() except: return None return cs def acc_new( cs, cb_accept, accs, quits ): acc = empty.new() accs.append( acc ) th_acc = thr.th_new( cb_accept, ( acc, ) ) def quit(): if not th_acc.quit_ev.is_set(): th_acc.quit_ev.set() if acc in accs: accs.remove( acc ) quits.append( acc ) def stop(): quit() th_acc.stop() if acc in quits: quits.remove( acc ) empty.add( acc, locals() ) th_acc.start() return acc def srv_new( port, cb_accept ): srv = empty.new() ss = srv_sock_new( port ) accs = [] quits = [] def gc(): while quits: acc = quits.pop( 0 ) acc.stop() def f_loop(): cs = accept( ss ) if not cs: return acc_new( cs, cb_accept, accs, quits ) gc() th = thr.loop_new( f_loop ) th.start() def stop(): th.quit_ev.set() close( ss ) th.stop() while accs: acc = accs.pop( 0 ) acc.stop() gc() return empty.add( srv, locals() ) def cb_accept( acc ): i = 0 while True: s = str( i ) print( "srv> send {}".format( s ) ) r = send( acc.cs, s ) print( "srv send r={}".format( r ) ) i += 1 time.sleep( 1 ) def run(): argv = sys.argv[ 1 : ] port = 1234 quit_ev = thr.event_new() if not argv: # srv srv_new( port, cb_accept ) quit_ev.wait() return # cli host = argv[ 0 ] cs = conn( port, host ) print( "cli conn {}".format( cs ) ) if not cs: return def cb( s ): print( "cli recv {}".format( s ) ) recv_th = recv_thr_new( cs, cb ) quit_ev.wait() if __name__ == "__main__": run() # EOF