1#Server Script
2import socket
3import select
4import sys
5from thread import *
6
7"""The first argument AF_INET is the address domain of the
8socket. This is used when we have an Internet Domain with
9any two hosts The second argument is the type of socket.
10SOCK_STREAM means that data or characters are read in
11a continuous flow."""
12server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
13server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
14
15# checks whether sufficient arguments have been provided
16if len(sys.argv) != 3:
17 print("Correct usage: script, IP address, port number")
18 exit()
19
20# takes the first argument from command prompt as IP address
21IP_address = str(sys.argv[1])
22
23# takes second argument from command prompt as port number
24Port = int(sys.argv[2])
25
26"""
27binds the server to an entered IP address and at the
28specified port number.
29The client must be aware of these parameters
30"""
31server.bind((IP_address, Port))
32
33"""
34listens for 100 active connections. This number can be
35increased as per convenience.
36"""
37server.listen(100)
38
39list_of_clients = []
40
41def clientthread(conn, addr):
42
43 # sends a message to the client whose user object is conn
44 conn.send("Welcome to this chatroom!")
45
46 while True:
47 try:
48 message = conn.recv(2048)
49 if message:
50
51 """prints the message and address of the
52 user who just sent the message on the server
53 terminal"""
54 print("<" + addr[0] + "> " + message )
55
56 # Calls broadcast function to send message to all
57 message_to_send = "<" + addr[0] + "> " + message
58 broadcast(message_to_send, conn)
59
60 else:
61 """message may have no content if the connection
62 is broken, in this case we remove the connection"""
63 remove(conn)
64
65 except:
66 continue
67
68"""Using the below function, we broadcast the message to all
69clients who's object is not the same as the one sending
70the message """
71def broadcast(message, connection):
72 for clients in list_of_clients:
73 if clients!=connection:
74 try:
75 clients.send(message)
76 except:
77 clients.close()
78
79 # if the link is broken, we remove the client
80 remove(clients)
81
82"""The following function simply removes the object
83from the list that was created at the beginning of
84the program"""
85def remove(connection):
86 if connection in list_of_clients:
87 list_of_clients.remove(connection)
88
89while True:
90
91 """Accepts a connection request and stores two parameters,
92 conn which is a socket object for that user, and addr
93 which contains the IP address of the client that just
94 connected"""
95 conn, addr = server.accept()
96
97 """Maintains a list of clients for ease of broadcasting
98 a message to all available people in the chatroom"""
99 list_of_clients.append(conn)
100
101 # prints the address of the user that just connected
102 print(addr[0] + " connected")
103
104 # creates and individual thread for every user
105 # that connects
106 start_new_thread(clientthread,(conn,addr))
107
108conn.close()
109server.close()
110
111#Client Script
112# Python program to implement client side of chat room.
113import socket
114import select
115import sys
116
117server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
118if len(sys.argv) != 3:
119 print("Correct usage: script, IP address, port number")
120 exit()
121IP_address = str(sys.argv[1])
122Port = int(sys.argv[2])
123server.connect((IP_address, Port))
124
125while True:
126
127 # maintains a list of possible input streams
128 sockets_list = [sys.stdin, server]
129
130 """ There are two possible input situations. Either the
131 user wants to give manual input to send to other people,
132 or the server is sending a message to be printed on the
133 screen. Select returns from sockets_list, the stream that
134 is reader for input. So for example, if the server wants
135 to send a message, then the if condition will hold true
136 below.If the user wants to send a message, the else
137 condition will evaluate as true"""
138 read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])
139
140 for socks in read_sockets:
141 if socks == server:
142 message = socks.recv(2048)
143 print(message)
144 else:
145 message = sys.stdin.readline()
146 server.send(message)
147 sys.stdout.write("<You>")
148 sys.stdout.write(message)
149 sys.stdout.flush()
150server.close()
151
152
153# Server (host) should have the top server script and the clients should have the client script. Both are labelled with a comment
1from p2p_python.utils import setup_p2p_params, setup_logger
2from p2p_python.server import Peer2Peer, Peer2PeerCmd
3import logging
4import asyncio
5import aiomonitor
6import time
7
8loop = asyncio.get_event_loop()
9log = logging.getLogger(__name__)
10
11setup_logger(logging.INFO)
12
13# setup Peer2Peer
14setup_p2p_params(
15 network_ver=11111, # (int) identify other network
16 p2p_port=2000, # (int) P2P listen port
17 p2p_accept=True, # (bool) switch on TCP server
18 p2p_udp_accept=True, # (bool) switch on UDP server
19)
20p2p = Peer2Peer(listen=100) # allow 100 connection
21p2p.setup()
22
23# close method example
24def close():
25 p2p.close()
26 loop.call_later(1.0, loop.stop)
27
28# You can setup DirectDmd method
29class DirectCmd(object):
30
31 @staticmethod
32 async def what_is_your_name(user, data):
33 print("what_is_your_name", user, data)
34 return {"you return": time.time()}
35
36 @staticmethod
37 async def get_time_now(user, data):
38 print("get_time_now", user, data)
39 return {"get time now": time.time()}
40
41# register methods for DirectCmd
42p2p.event.setup_events_from_class(DirectCmd)
43# throw cmd by `await p2p.send_direct_cmd(DirectCmd.what_is_your_name, 'kelly')`
44# or `await p2p.send_direct_cmd('what_is_your_name', 'kelly')`
45
46# You can setup broadcast policy (default disabled)
47# WARNING: You must set strict policy or will be broken by users
48async def broadcast_check_normal(user, data):
49 return True
50
51# overwrite method
52p2p.broadcast_check = broadcast_check_normal
53
54# setup netcat monitor
55local = locals().copy()
56local.update({k: v for k, v in globals().items() if not k.startswith('__')})
57log.info('local', list(local.keys()))
58aiomonitor.start_monitor(loop, port=3000, locals=local)
59log.info(f"you can connect by `nc 127.0.0.1 3000`")
60
61# start event loop
62# close by `close()` on netcat console
63try:
64 loop.run_forever()
65except KeyboardInterrupt:
66 log.info("closing")
67loop.close()
68