前言:
通过网站的寻找,以及自己的一些尝试,终于完成了多个客户端向服务器端发送请求,并且服务器端可以通过一些规则设置,向满足要求的客户端发送消息,并设置了延时处理等操作。
Server端:
from socket import *
from time import ctime
import threading
import time
import data_pb2
import data_pb2_grpc
import base64
import struct
import produce_resource
# 转小端
_struct_int_low = struct.Struct('<I')
# ----------- 配置信息 -------------
max_count_nums = 20 # 延时设置 [通过循环次数来判断是否超时]
max_resource_num = 5 # 设置资源数
cur_resource_num = 0 # 当前申请资源数
time_client = {} # 为每一客户端都计算一个时长
room_id_pool = [] # 设置roomID_list
ai_ip_pool = [] # 设置AI服务器资源
ai_port_pool = []
game_core_ip_pool = [] # 设置game_core服务器资源
game_core_port_pool = []
sync_server_ip_pool = [] # 设置sync_server服务器资源
sync_server_port_pool = []
# 指定警察和土匪 【游戏规则】
nums_ai = 3
nums_player = 2
police_nums = 1
gangster_nums = 1
client_content = {} # 存储客户端玩家信息
socks = {} # 放每个客户端的socket
cur_police_num = 0 # 初始化警察和土匪的数量, 以及信息列表
cur_gangster_num = 0
save_socket_address = [] # 存储满足匹配条件客户端的id
save_release_resource = {} # 记录已经被释放的资源
BUFSIZ = 1024 # 接受数据大小
tcpSerSock = None
# ---------------------------------------
def init():
"""
初始化客户端
:return:
"""
host = ''
port = 2150
addr = (host, port)
global tcpSerSock
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(addr)
tcpSerSock.listen(5) # 最大等待数(有很多人理解为最大连接数,其实是错误的)
print("服务端已启动,等待客户端连接。。。。")
def accept_client():
"""
接受客户端的连接
:return:
"""
while True:
client, info = tcpSerSock.accept() # 阻塞,等待客户端连接
start_time = time.time()
print('connected from:', info, " start_time is:", start_time)
# 给每个客户端创建一个独立的线程进行管理
thread_ = threading.Thread(target=message_handle, args=(client, info))
# 设置成守护线程【当所有用户线程结束之后,守护线程才结束】
thread_.setDaemon(True)
thread_.start()
def message_handle(client, info):
"""
消息处理
:param client: 客户端的信息
:param info: 客户端的地址
:return:
"""
client.send("连接服务器成功 !!!".encode(encoding='utf8'))
# while True:
try:
# ------ proto数据进行反序列化操作-------
# head_data = client.recv(4) # 接收数据头 4个字节
# data_len = int.from_bytes(head_data, byteorder='big')
# proto_data = client.recv(data_len)
# t_message = data_pb2.LServerResponse()
# t_message.ParseFromString(proto_data)
# -------------------------------------
# ------ 解析从客户端传入的数据(base64) ---------
# message = client.recv(BUFSIZ)
# length, ignore, message = message.partition(b':')
# message = base64.b64decode(message)
# # 接收proto_buf数据格式
# t_message = data_pb2.LServerRequest()
# # 数据准换成proto_buf的格式
# t_message.ParseFromString(message)
# -------------------------------------
# 使用 struct 来解析数据 --------
mess = client.recv(BUFSIZ)
length = mess[:4]
# 使用小端进行解析
length = _struct_int_low.unpack(length)[0]
data = mess[4:]
buffer = b''
recv_size = 3
while length > 0:
buffer += data[:recv_size]
data = data[recv_size:]
length -= recv_size
t_message = data_pb2.LServerRequest()
t_message.ParseFromString(buffer)
# -------------------------------------
client_information = data_pb2.ClientInfo()
client_information.CopyFrom(t_message.client_info)
print(t_message.type, " ", client_information.uuid, " ", client_information.player_role, " ",
client_information.is_ai)
print(" ----- successful, client data from {info}: -----".format(info=info))
# 客户端 发送 MATCH 到联机服务器上
if t_message.type is data_pb2.LServerType.L_MATCH:
global cur_resource_num
cur_resource_num += 1
print("玩家开始匹配。。。。")
# client_content[str(info[1])] = client_information
# socks[str(info[1])] = client
# 将客户端信息,保存【用字典保存】 [使用玩家id作为key]
client_content[t_message.client_info.uuid] = client_information