├── .gitignore ├── requirements.txt └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | kademlia==2.2.2 2 | netifaces==0.11.0 3 | PyQt6==6.4.0 4 | PyQt6-Qt6==6.4.1 5 | PyQt6-sip==13.4.0 6 | pyzmq==24.0.1 7 | rpcudp==4.0.2 8 | u-msgpack-python==2.7.2 9 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | """Decentralized chat example""" 2 | try: 3 | raw_input 4 | except NameError: 5 | raw_input = input 6 | 7 | import argparse 8 | import os 9 | from threading import Thread 10 | 11 | # dependency, not in stdlib 12 | from netifaces import interfaces, ifaddresses, AF_INET 13 | 14 | import zmq 15 | 16 | 17 | def listen(masked): 18 | """listen for messages 19 | 20 | masked is the first three parts of an IP address: 21 | 22 | 192.168.1 23 | 24 | The socket will connect to all of X.Y.Z.{1-254}. 25 | """ 26 | ctx = zmq.Context.instance() 27 | listener = ctx.socket(zmq.SUB) 28 | for last in range(1, 255): 29 | listener.connect("tcp://{0}.{1}:9000".format(masked, last)) 30 | 31 | listener.setsockopt(zmq.SUBSCRIBE, b'') 32 | while True: 33 | try: 34 | print(listener.recv_string()) 35 | except (KeyboardInterrupt, zmq.ContextTerminated): 36 | break 37 | 38 | 39 | def main(): 40 | parser = argparse.ArgumentParser() 41 | parser.add_argument("interface", type=str, help="the network interface", 42 | choices=interfaces(), 43 | ) 44 | parser.add_argument("user", type=str, default=os.environ['USER'], 45 | nargs='?', 46 | help="Your username", 47 | ) 48 | args = parser.parse_args() 49 | inet = ifaddresses(args.interface)[AF_INET] 50 | addr = inet[0]['addr'] 51 | masked = addr.rsplit('.', 1)[0] 52 | 53 | ctx = zmq.Context.instance() 54 | 55 | listen_thread = Thread(target=listen, args=(masked,)) 56 | listen_thread.start() 57 | 58 | bcast = ctx.socket(zmq.PUB) 59 | bcast.bind("tcp://%s:9000" % args.interface) 60 | print("starting chat on %s:9000 (%s.*)" % (args.interface, masked)) 61 | while True: 62 | try: 63 | msg = raw_input() 64 | bcast.send_string("%s: %s" % (args.user, msg)) 65 | except KeyboardInterrupt: 66 | break 67 | bcast.close(linger=0) 68 | ctx.term() 69 | 70 | 71 | if __name__ == '__main__': 72 | main() 73 | --------------------------------------------------------------------------------