-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.py
167 lines (142 loc) · 6.08 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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import socket
import _thread
import pickle
from struct import pack, unpack
from game import Hanabi
ip_address = "192.168.0.15"
# ip_address = "127.0.0.1"
port = 5555
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((ip_address, port))
sock.listen()
print("Server listening, waiting for connection ...")
def send_data(conn, data):
try:
pickled_data = pickle.dumps(data)
length = pack('>Q', len(pickled_data))
conn.sendall(length)
conn.sendall(pickled_data)
return None
except Exception as e:
print("exception in in server.py send_data")
print(e)
def receive_data(conn):
try:
bs = conn.recv(8)
(length,) = unpack('>Q', bs)
data = b''
while len(data) < length:
to_read = length - len(data)
data += conn.recv(
4096 if to_read > 4096 else to_read)
return pickle.loads(data)
except Exception as e:
print("exception in in server.py receive_data")
print(e)
def threaded_client(conn, client_address):
global id_new_game
while True:
try:
data = receive_data(conn)
except EOFError: # what is this?? raised when the socket is empty and you call recv
data = ''
pass
if not data:
break
elif isinstance(data, str):
if data == "get_avail_games":
avail_game_pool = {}
for x in game_pool:
if game_pool[x]._num_connections < game_pool[x].nb_players:
avail_game_pool[x] = game_pool[x]
send_data(conn, avail_game_pool)
elif data.startswith('start'):
print("client_adress:", client_address)
nb_players = int(data[-1])
print(
f'Creating new game for {nb_players} players. ID: {id_new_game}')
# TODO change seed for randomness
game = Hanabi(nb_players, id_new_game, seed=id_new_game)
p_nbr = 0
game_pool[id_new_game] = game
players_connected_to_game[id_new_game] = [client_address]
ips_p_nbrs[id_new_game] = {client_address[0]: p_nbr}
print("ips_p_nbrs:", ips_p_nbrs)
id_game = id_new_game
id_new_game += 1
send_data(conn, p_nbr)
elif data.startswith('join'):
id_game = int(data[-1])
game = game_pool.get(id_game, None)
if game is not None:
nb_connected = len(players_connected_to_game[id_game])
# below should have the goal of making sure there are no problems with two different clients choosing a agme with 1 spot left at roughly the same time
if nb_connected < game.nb_players:
print("client_adress:", client_address)
if client_address[0] in ips_p_nbrs[id_game]:
print(
f'Re-adding {client_address} to game {id_game}')
players_connected_to_game[id_game].append(
client_address)
game._num_connections = len(
players_connected_to_game[id_game])
p_nbr = ips_p_nbrs[id_game][client_address[0]]
elif len(ips_p_nbrs[id_game]) < game.nb_players:
print(f'Adding {client_address} to game {id_game}')
players_connected_to_game[id_game].append(
client_address)
game._num_connections = len(
players_connected_to_game[id_game])
p_nbr = nb_connected # player number
ips_p_nbrs[id_game][client_address[0]] = p_nbr
print("ips_p_nbrs:", ips_p_nbrs)
else:
send_data(conn, "choose_again")
print('Trying to join full game', client_address)
continue
if game._num_connections == game.nb_players:
game._ready = True
send_data(conn, p_nbr)
else:
send_data(conn, "choose_again")
print('Trying to join full game', client_address)
elif data == "get":
try:
send_data(conn, game)
except:
break
else: # data is not instance of str
game.update_table(data)
if game._finished:
game_pool.pop(game._id_game, None)
players_connected_to_game.pop(game._id_game, None)
ips_p_nbrs.pop(game._id_game, None)
try:
send_data(conn, game)
except:
break
print("Lost connection")
print('Closing connection with:', client_address)
conn.close()
if getattr(game, '_finished', 0) is None: # game hasn't finished
# Wait for player to come back
address_list = players_connected_to_game[game._id_game]
if client_address in address_list:
address_list.remove(client_address)
nb_connected = len(address_list)
game_pool[game._id_game]._num_connections = nb_connected
if nb_connected == 0:
game_pool.pop(game._id_game, None)
players_connected_to_game.pop(game._id_game, None)
ips_p_nbrs.pop(game._id_game, None)
elif nb_connected != game_pool[game._id_game].nb_players:
# TODO: I think this can be done immediately right? no if statement
game_pool[game._id_game]._ready = False
game_pool = {}
players_connected_to_game = {}
ips_p_nbrs = {}
id_new_game = 0
while True:
conn, client_addr = sock.accept()
print("Connected to:", client_addr)
_thread.start_new_thread(threaded_client, (conn, client_addr))