stdinsrv.py (2433B)
1 #!/usr/bin/env python 2 # coding=utf-8 3 # 4 # Copy me if you can. 5 # by Christoph Lohmann <20h@r-36.net> 6 # 7 8 import sys 9 from socket import socket, AF_INET, SOCK_STREAM, SO_REUSEADDR, SOL_SOCKET 10 from select import poll, POLLIN, POLLPRI, POLLERR, POLLHUP 11 from fcntl import fcntl, F_GETFL, F_SETFL 12 from os import O_NONBLOCK 13 import errno 14 import time 15 from getopt import getopt, GetoptError 16 17 def dbg(msg): 18 sys.stderr.write("%s\n" % (msg)) 19 20 def usage(app): 21 sys.stderr.write("usage: %s [-d] [-p port] [-h bind host]\n" % (app)) 22 sys.exit(1) 23 24 def main(args): 25 try: 26 opts, args = getopt(args[1:], "dp:h:") 27 except GetoptError, err: 28 sys.stderr.write("%s\n" % (str(err))) 29 usage(args[0]) 30 31 debug = False 32 host = "" 33 port = 6789 34 for o, a in opts: 35 if o == "-p": 36 port = int(a) 37 elif o == "-d": 38 debug = True 39 elif o == "-h": 40 host = a 41 else: 42 assert False, "unhandled option" 43 44 sock = socket(AF_INET, SOCK_STREAM) 45 sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 46 sock.bind((host, port)) 47 sock.listen(5) 48 49 fl = fcntl(sys.stdin, F_GETFL) 50 fcntl(sys.stdin, F_SETFL, fl | O_NONBLOCK) 51 52 clients = [] 53 def getcli(fd): 54 for i in clients: 55 if i.fileno() == fd: 56 return i 57 58 def broadcastcli(data): 59 if debug == True: 60 dbg("Broadcast") 61 for i in clients: 62 try: 63 i.send(data) 64 i.flush(data) 65 except: 66 next 67 68 def closecli(fd): 69 if debug == True: 70 dbg("Close: %d" % (fd)) 71 cli = getcli(i[0]) 72 clients.remove(cli) 73 po.unregister(cli) 74 cli.close() 75 76 po = poll() 77 po.register(sys.stdin, POLLIN|POLLPRI|POLLERR|POLLHUP) 78 po.register(sock, POLLIN|POLLPRI) 79 while 1: 80 events = po.poll(30) 81 for i in events: 82 if i[0] == sock.fileno(): 83 cli = sock.accept()[0] 84 cli.setblocking(0) 85 clients.append(cli) 86 po.register(cli, POLLIN|POLLPRI) 87 if debug == True: 88 dbg("Accept: %d" % (cli.fileno())) 89 elif i[1] in (POLLERR, POLLHUP): 90 if debug == True: 91 dbg("err or hup: %d" % (i[0])) 92 if i[0] == sys.stdin.fileno(): 93 return 1 94 cli = getcli(i[0]) 95 clients.remove(cli) 96 po.unregister(cli) 97 cli.close() 98 elif i[1] in (POLLIN, POLLPRI): 99 if i[0] == sys.stdin.fileno(): 100 if debug == True: 101 dbg("Input on stdin.") 102 broadcastcli(sys.stdin.read(4096)) 103 else: 104 if debug == True: 105 dbg("Input from client: %d" % (i[0])) 106 cli = getcli(i[0]) 107 a = cli.recv(4096) 108 if len(a) == 0: 109 closecli(i[0]) 110 111 if __name__ == "__main__": 112 sys.exit(main(sys.argv)) 113