-
Notifications
You must be signed in to change notification settings - Fork 11
/
server.py
106 lines (87 loc) · 4.27 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# Tcp Chat server
import socket, select
class Server(object):
# List to keep track of socket descriptors
CONNECTION_LIST = []
RECV_BUFFER = 4096 # Advisable to keep it as an exponent of 2
PORT = 5000
def __init__(self):
self.user_name_dict = {}
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_up_connections()
self.client_connect()
def set_up_connections(self):
# this has no effect, why ?
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind(("0.0.0.0", self.PORT))
self.server_socket.listen(10) # max simultaneous connections.
# Add server socket to the list of readable connections
self.CONNECTION_LIST.append(self.server_socket)
# Function to broadcast chat messages to all connected clients
def broadcast_data(self, sock, message):
# Do not send the message to master socket and the client who has send us the message
for socket in self.CONNECTION_LIST:
if socket != self.server_socket and socket != sock:
# if not send_to_self and sock == socket: return
try:
socket.send(message)
except:
# broken socket connection may be, chat client pressed ctrl+c for example
socket.close()
self.CONNECTION_LIST.remove(socket)
def send_data_to(self, sock, message):
try:
sock.send(message)
except:
# broken socket connection may be, chat client pressed ctrl+c for example
socket.close()
self.CONNECTION_LIST.remove(sock)
def client_connect(self):
print "Chat server started on port " + str(self.PORT)
while 1:
# Get the list sockets which are ready to be read through select
read_sockets, write_sockets, error_sockets = select.select(self.CONNECTION_LIST, [], [])
for sock in read_sockets:
# New connection
if sock == self.server_socket:
# Handle the case in which there is a new connection recieved through server_socket
self.setup_connection()
# Some incoming message from a client
else:
# Data recieved from client, process it
try:
# In Windows, sometimes when a TCP program closes abruptly,
# a "Connection reset by peer" exception will be thrown
data = sock.recv(self.RECV_BUFFER)
if data:
if self.user_name_dict[sock].username is None:
self.set_client_user_name(data, sock)
else:
self.broadcast_data(sock, "\r" + '<' + self.user_name_dict[sock].username + '> ' + data)
except:
self.broadcast_data(sock, "Client (%s, %s) is offline" % addr)
print "Client (%s, %s) is offline" % addr
sock.close()
self.CONNECTION_LIST.remove(sock)
continue
self.server_socket.close()
def set_client_user_name(self, data, sock):
self.user_name_dict[sock].username = data.strip()
self.send_data_to(sock, data.strip() + ', you are now in the chat room\n')
self.send_data_to_all_regesterd_clents(sock, data.strip() + ', has joined the cat room\n')
def setup_connection(self):
sockfd, addr = self.server_socket.accept()
self.CONNECTION_LIST.append(sockfd)
print "Client (%s, %s) connected" % addr
self.send_data_to(sockfd, "please enter a username: ")
self.user_name_dict.update({sockfd: Connection(addr)})
def send_data_to_all_regesterd_clents(self, sock, message):
for local_soc, connection in self.user_name_dict.iteritems():
if local_soc != sock and connection.username is not None:
self.send_data_to(local_soc, message)
class Connection(object):
def __init__(self, address):
self.address = address
self.username = None
if __name__ == "__main__":
server = Server()