C
castironpi
#interactive run -i
import threading
import Queue
import functools
class GenThread( threading.Thread, Queue.Queue ):
_taskid= 0
def __init__( self, *ar, **kw ):
threading.Thread.__init__( self, *ar, **kw )
Queue.Queue.__init__( self )
self.setDaemon( True )
self.start()
self._doneevents= {}
def run( self ):
while 1:
id, fun, ar, kw= self.get()
self._= fun( *ar, **kw )
self._doneevents[id].set()
if self._:
self._print( self._ )
def me( self, fun, *ar, **kw ):
id= GenThread._taskid
GenThread._taskid+= 1
self.put( ( id, fun, ar, kw ) )
self._doneevents[ id ]= e= threading.Event()
return e
def _print( self, *ar, **kw ):
print( self.getName(), *ar, **kw )
for i in range( 10 ):
exec( 'th%i= GenThread()'% i )
import socket
host= socket.socket( socket.AF_INET,
socket.SOCK_STREAM )
host.bind( ( '', 8000 ) )
th1.me( host.listen, 1 )
_acc= th1.me( host.accept )
cli= socket.socket( socket.AF_INET,
socket.SOCK_STREAM )
th2.me( cli.connect, ( 'localhost', 8000 ) )
_acc.wait()
conn= th1._[0]
ConnClose= object()
class IncompleteTransmission( Exception ): pass
def _draintilclose( conn, understandfun= None ):
while 1:
_preamb= ''
while 1:
_data= conn.recv( 1 )
if not _data:
conn.close()
return ConnClose
if _data== b'\x00':
break
_preamb+= _data.decode()
_len= int( _preamb, 16 )
_lenleft= _len
_curmsg= bytearray()
while _lenleft:
_data= conn.recv( min( 4096, _lenleft ) )
if not _data:
raise IncompleteTransmission
_curmsg.extend( _data )
_lenleft-= len( _data )
assert len( _curmsg )== _len
if None is not understandfun:
understandfun( _curmsg )
def _dressandsend( sck, msg ):
_preamble= hex( len( msg ) )[2:]+ '\x00'
_dressed= bytes( _preamble, 'ascii' )+ msg
_lenleft= len( _dressed )
while _lenleft:
_sent= sck.send( _dressed[-_lenleft:] )
_lenleft-= _sent
th1.me( _draintilclose, conn, th1._print )
th2.me( _draintilclose, cli, th2._print )
This is cool! Set up a socket and listen 'til close on one thread,
print output by default as complete messages are received. Listen
'til close, same, on another, th1, th2 respectively. Roughly off the
console:
Thread-1 bytearray(b'def')
Rearranged the '>>>'. It's damn annoying. Probably a specialized
stdout to detect when in a prompt and add extra newline, maybe
modified GenThread._print. Someone go replace hex with base255 and
conn.recv( 1 ) with conn.recv( 2 ). Should take any length-- base256
over hex is just a factor of 2, and still O( log( message length ) ).
['ConnClose', 'GenThread', 'IncompleteTransmission', 'Queue',
'__builtins__', '__doc__', '__name__', '__package__', '_acc',
'_draintilclose', '_dressandsend', 'cli', 'conn', 'functools', 'host',
'i', 'socket', 'th1', 'th2', 'th3', 'th4', 'th5', 'th6', 'th7', 'th8',
'th9', 'threading']
import threading
import Queue
import functools
class GenThread( threading.Thread, Queue.Queue ):
_taskid= 0
def __init__( self, *ar, **kw ):
threading.Thread.__init__( self, *ar, **kw )
Queue.Queue.__init__( self )
self.setDaemon( True )
self.start()
self._doneevents= {}
def run( self ):
while 1:
id, fun, ar, kw= self.get()
self._= fun( *ar, **kw )
self._doneevents[id].set()
if self._:
self._print( self._ )
def me( self, fun, *ar, **kw ):
id= GenThread._taskid
GenThread._taskid+= 1
self.put( ( id, fun, ar, kw ) )
self._doneevents[ id ]= e= threading.Event()
return e
def _print( self, *ar, **kw ):
print( self.getName(), *ar, **kw )
for i in range( 10 ):
exec( 'th%i= GenThread()'% i )
import socket
host= socket.socket( socket.AF_INET,
socket.SOCK_STREAM )
host.bind( ( '', 8000 ) )
th1.me( host.listen, 1 )
_acc= th1.me( host.accept )
cli= socket.socket( socket.AF_INET,
socket.SOCK_STREAM )
th2.me( cli.connect, ( 'localhost', 8000 ) )
_acc.wait()
conn= th1._[0]
ConnClose= object()
class IncompleteTransmission( Exception ): pass
def _draintilclose( conn, understandfun= None ):
while 1:
_preamb= ''
while 1:
_data= conn.recv( 1 )
if not _data:
conn.close()
return ConnClose
if _data== b'\x00':
break
_preamb+= _data.decode()
_len= int( _preamb, 16 )
_lenleft= _len
_curmsg= bytearray()
while _lenleft:
_data= conn.recv( min( 4096, _lenleft ) )
if not _data:
raise IncompleteTransmission
_curmsg.extend( _data )
_lenleft-= len( _data )
assert len( _curmsg )== _len
if None is not understandfun:
understandfun( _curmsg )
def _dressandsend( sck, msg ):
_preamble= hex( len( msg ) )[2:]+ '\x00'
_dressed= bytes( _preamble, 'ascii' )+ msg
_lenleft= len( _dressed )
while _lenleft:
_sent= sck.send( _dressed[-_lenleft:] )
_lenleft-= _sent
th1.me( _draintilclose, conn, th1._print )
th2.me( _draintilclose, cli, th2._print )
This is cool! Set up a socket and listen 'til close on one thread,
print output by default as complete messages are received. Listen
'til close, same, on another, th1, th2 respectively. Roughly off the
console:
Thread-1 bytearray(b'def')
Rearranged the '>>>'. It's damn annoying. Probably a specialized
stdout to detect when in a prompt and add extra newline, maybe
modified GenThread._print. Someone go replace hex with base255 and
conn.recv( 1 ) with conn.recv( 2 ). Should take any length-- base256
over hex is just a factor of 2, and still O( log( message length ) ).
['ConnClose', 'GenThread', 'IncompleteTransmission', 'Queue',
'__builtins__', '__doc__', '__name__', '__package__', '_acc',
'_draintilclose', '_dressandsend', 'cli', 'conn', 'functools', 'host',
'i', 'socket', 'th1', 'th2', 'th3', 'th4', 'th5', 'th6', 'th7', 'th8',
'th9', 'threading']