Skip to content

Instantly share code, notes, and snippets.

@agumonkey
Last active September 27, 2019 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agumonkey/728dab8a943eaa7f3171bf34805fb0a1 to your computer and use it in GitHub Desktop.
Save agumonkey/728dab8a943eaa7f3171bf34805fb0a1 to your computer and use it in GitHub Desktop.
Learning
'''
tcpcs
'''
import sys
import time
import threading
import socket
import socketserver
NL = b"\n"
def enstring(o):
''' 'a -> str '''
if isinstance(o, bytes):
return o.decode()
elif not isinstance(o, str):
return str(o)
else:
return o
def prn(*args, sep=" ", end="\n"):
''' thread-safe stdout.write '''
lock = threading.Lock()
lock.acquire()
for arg in args:
sys.stdout.write(enstring(arg))
sys.stdout.write(sep)
if end:
sys.stdout.write(end)
lock.release()
class Shouter(socketserver.StreamRequestHandler):
''' Shouter '''
def __init__(self, rrr, clientaddr, selph):
''' <doc> '''
prn("handler:", "Shout!")
super().__init__(rrr, clientaddr, selph)
def handle(self):
''' <doc> '''
while True:
message = self.rfile.readline().strip()
if message:
received = message.upper() # + NL
# prn('handler.out:', r)
try:
self.wfile.write(received)
self.wfile.flush()
except BrokenPipeError as exn:
prn(f"handler: woops {exn}")
break
else:
prn("handler: closing pipe")
self.rfile.close()
self.wfile.close()
break
class Serv:
''' Serv '''
def __init__(self, host="localhost", port=8080):
''' <doc> '''
prn("server: init")
self.port = port
self.sock = socketserver.TCPServer((host, port), Shouter)
prn("server:", "---- config ----")
prn("server:", f"fileno := {self.sock.fileno()}")
prn("server:", f"socket := {self.sock.socket}")
prn("server:", f"address_family := {self.sock.address_family}")
prn("server:", f"RequestHandlerClass := {self.sock.RequestHandlerClass}")
prn("server:", f"server_address := {self.sock.server_address}")
prn("server:", f"allow_reuse_address := {self.sock.allow_reuse_address}")
prn("server:", f"request_queue_size := {self.sock.request_queue_size}")
prn("server:", f"socket_type := {self.sock.socket_type}")
prn("server:", f"timeout := {self.sock.timeout}")
prn("server:", "---- ----")
def run(self):
''' <doc> '''
prn(f"server: listening on {self.port}")
self.sock.serve_forever()
def close(self):
''' <doc> '''
prn("server: shutdown")
self.sock.shutdown()
class Client:
''' <doc> '''
def __init__(self, host="localhost", port=8080, timeout=2):
''' <doc> '''
self.port = port
prn(f"client: make socket {host}:{port}")
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(timeout)
prn(f"client: connect")
self.sock.connect((host, port))
def word(self):
''' <doc> '''
return "foobar"
def talk(self, num=6, delay=1):
''' <doc> '''
prn(f"client: talk {num} times, delay of {delay}")
for index in range(num):
try:
message = f"{self.word()} {index}".encode()
prn("--")
byte = self.sock.send(message + NL)
prn("client:", "sent", message, byte)
received = self.sock.recv(1024)
prn("client:", "got", received)
time.sleep(delay)
except Exception as exn:
prn(f"woops {index}")
prn(f" [exn] {exn}")
time.sleep(delay)
prn("client: bye")
self.clean()
prn("client: bye")
def clean(self):
''' <doc> '''
self.sock.shutdown(0)
prn("client: shutdown")
self.sock.close()
prn("client: close")
def main():
''' <doc> '''
# s = Serv()
# c = Client()
# t = threading.Thread(target=s.run)
# t.start()
# delay = 1
# prn(f"[main] idle {delay} seconds...")
# time.sleep(delay)
# u = threading.Thread(target=c.talk)
# u.start()
server = Serv()
threading.Thread(target=server.run).start()
threading.Thread(target=Client().talk).start()
delay = 10
prn(f"[main] idle {delay} seconds...")
time.sleep(delay)
prn("--")
server.close()
prn("main: done")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment