You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SafariChess/network/server.py

247 lines
6.1 KiB

# coding:utf-8
import socket
import sys
import json
import uuid
import time
from threading import Thread, Lock
if(sys.version[:1] == "3"):
import queue as Queue
from _thread import *
else:
import Queue
from thread import *
class Config:
SOCKET_HOST = '127.0.0.1' # Symbolic name meaning all available interfaces
SOCKET_PORT = 50005 # Arbitrary non-privileged port
MAX_WAITING_TIME = 180
MAX_THNIKING_TIME = 60
MAX_TOTAL_TIME = 600
class Client:
def __init__(self, conn, addr, name, side, time, total):
self.conn = conn
self.addr = addr
self.name = name
self.side = side
self.time = time
self.total = total
mutex = Lock()
mutex_playing = Lock()
playing_ones = {}
waiting_players = Queue.Queue()
#init queues
#for games in range(1, 10):
# waiting_players[games] = Queue.Queue()
def load_config():
with open('config.txt', 'r') as f:
for line in f.readlines():
line = line.strip()
if line.find('SOCKET_HOST=') >= 0:
Config.SOCKET_HOST = line[line.index('=') + 1 : ]
elif line.find('SOCKET_PORT=') >= 0:
Config.SOCKET_PORT = int(line[line.index('=') + 1 : ])
elif line.find('MAX_WAITING_TIME=') >= 0:
Config.MAX_WAITING_TIME = int(line[line.index('=') + 1 : ])
elif line.find('MAX_THNIKING_TIME=') >= 0:
Config.MAX_THNIKING_TIME = int(line[line.index('=') + 1 : ])
elif line.find('MAX_TOTAL_TIME=') >= 0:
Config.MAX_TOTAL_TIME = int(line[line.index('=') + 1 : ])
else:
pass
def get_counterpart_from(waiting_ones):
counterpart = None
mutex.acquire()
if not waiting_ones.empty():
counterpart = waiting_ones.get()
mutex.release()
return counterpart
def to_wait_in_queue(client, the_queue):
mutex.acquire()
the_queue.put(client)
mutex.release()
def remove_one_from_queue(the_queue):
mutex.acquire()
if (the_queue.qsize() == 1):
the_queue.get()
mutex.release()
def send_msg_to(client, msg):
packet = json.dumps(msg)
if (sys.version[:1] == "3"):
packet = packet.encode('utf-8')
#print(client.addr[0] + ":" + str(client.addr[1]) + "\t" + str(msg))
client.conn.send(packet)
def __start_match_between(client0, client1):
match_uuid = str(uuid.uuid4())
mutex_playing.acquire()
playing_ones[match_uuid] = (client0, client1)
mutex_playing.release()
client0.side = 0
client0.time = Config.MAX_THNIKING_TIME
client0.total = Config.MAX_TOTAL_TIME
client1.side = 1
client1.time = -1
client1.total = Config.MAX_TOTAL_TIME
msg0 = {
"status": 1,
"counterpart_name": client1.name,
"game_id": match_uuid,
"side": client0.side,
"think_time": Config.MAX_THNIKING_TIME,
"total_time": Config.MAX_TOTAL_TIME,
}
send_msg_to(client0, msg0)
msg1 = {
"status": 1,
"counterpart_name": client0.name,
"game_id": match_uuid,
"side": client1.side,
"think_time": Config.MAX_THNIKING_TIME,
"total_time": Config.MAX_TOTAL_TIME,
}
send_msg_to(client1, msg1)
def join_game_handler(msg, addr, conn):
new_client = Client(conn, addr, msg['name'], -1, -1, -1)
#game_type = msg["id"]
#the_queue = waiting_players[game_type]
counterpart = get_counterpart_from(waiting_players)
if not counterpart: #wait
to_wait_in_queue(new_client, waiting_players)
return
else:
#counterpart=get_counterpart_from(waiting_players[game_type])
__start_match_between(new_client, counterpart)
def quit_game_handler(msg):
match_uuid = msg['game_id']
if match_uuid is None:
remove_one_from_queue(waiting_players)
return
pairs = None
mutex_playing.acquire()
if (match_uuid in playing_ones):
pairs = playing_ones[match_uuid]
del playing_ones[match_uuid]
mutex_playing.release()
if pairs is not None:
if(pairs[0].side == msg['side']):
to_notify = pairs[1]
else:
to_notify = pairs[0]
msg = {
"status": 2, #exit
"game_id": match_uuid,
"side": msg['side'],
"request": msg['request'],
}
send_msg_to(to_notify, msg)
def timer_thread():
while True:
time.sleep(1)
mutex_playing.acquire()
for game_id in list(playing_ones.keys()):
(client0, client1) = playing_ones[game_id]
#print("%d - %d" % (client0.time, client1.time))
if (client0.time < 0):
client = client1
else:
client = client0
if (client.time == 0 or client.total == 0):
msg = {
"status": 3, #timeout exit
"game_id": game_id,
"side": client.side,
}
send_msg_to(client0, msg)
send_msg_to(client1, msg)
del playing_ones[game_id]
else:
client.time -= 1
client.total -= 1
mutex_playing.release()
def transfer_message(msg):
match_uuid = msg['game_id']
pairs = playing_ones[match_uuid]
if(pairs[0].side == msg['side']):
to_notify = pairs[1]
pairs[0].time = -1
else:
to_notify = pairs[0]
pairs[1].time = -1
to_notify.time = Config.MAX_THNIKING_TIME
send_msg_to(to_notify, msg)
def client_thread(conn, addr):
while True:
data = conn.recv(1024)
if not data:
break
print(data)
data = json.loads(data)
if not 'type' in data:
transfer_message(data['msg'])
continue
if data['type'] == 0:
join_game_handler(data['msg'], addr, conn)
continue
elif data['type'] == 1:
transfer_message(data['msg'])
continue
elif data['type'] == 2:
quit_game_handler(data['msg'])
break
elif data['type'] == 3:
break
else:
#delivering message between the two clients
transfer_message(data['msg'])
continue
#came out of loop
conn.close()
def main():
load_config()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket server created')
#try:
server.bind((Config.SOCKET_HOST, Config.SOCKET_PORT))
#except (socket.error, msg):
# print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
# sys.exit()
print('Socket bind complete')
server.listen(10)
print('Socket now listening')
#now keep talking with the client
start_new_thread(timer_thread, ())
3 years ago
while True: #! 监听本体
#wait to accept a connection - blocking call
conn, addr = server.accept()
print ('Connected with ' + addr[0] + ':' + str(addr[1]))
#start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
start_new_thread(client_thread, (conn, addr))
server.close()
if __name__ == '__main__':
main()