如何解决套接字两次发送数据
当我遇到一个错误,该错误会将数据发送两次时,我正在从事多人游戏。我在一个播放器上工作得很好,但是一旦另一个播放器加入服务器,数据将被发送两次。如果仅连接了一个客户端,则从服务器接收的数据如下所示:{"player locations": [[1,84,100,false,["n","a","m","e"]]]}
。当两个客户端连接时,这是从服务器接收的数据:
{"player locations": [[1,80,102,true,["P","l","y","e","r","O","n","e"]],[2,57,"T","w","o"]]]}{"player locations": [[1,"o"]]]}
这是服务器发送的数据
b'{"player locations": [[1,"o"]]]}'
IMPORTS/SETUP -------------------------------------------------------------------------------------------------------- #
import socket,sys,json
import threading
# FUNCTIONS ------------------------------------------------------------------------------------------------------------ #
def get_ip_port(path):
with open(path,"r") as ipf:
ipf_data = ipf.read()
ipf.close()
data_split = ipf_data.split(":")
return [data_split[0],int(data_split[1])]
print(get_ip_port("serverip.txt"))
def update_clients(updatemessage):
"""
update_data[0][0] is the player's x pos
update_data[0][1] is the player's y pos
update_data[1] is the player's flip bool
update_data[2] is the player's name str
:param updatemessage:
:return:
"""
# player key structure: {playerid:[[x,y],flip,name]}
update_data = json.loads(updatemessage)
playerid = [key for key in update_data.keys()][0]
update_lst = update_data[playerid]
playerid = update_lst[0]
#print(update_lst)
#print(playerid)
print(players)
if playerid == 0:
return
playermap[playerid][0][0] = update_lst[1]
playermap[playerid][0][1] = update_lst[2]
playermap[playerid][1] = update_lst[3]
playermap[playerid][2] = update_lst[4]
remove = []
for player_socket in players:
update = {'player locations':[]}
for key,value in playermap.items():
update['player locations'].append([key,value[0][0],value[0][1],value[1],value[2]])
try:
print(json.dumps(update).encode())
player_socket.sendall(json.dumps(update).encode())
except Exception as e:
remove.append(player_socket)
print(e)
continue
for r in remove:
players.remove(r)
def client_thread(conn,player_id):
while True:
try:
recvdata = conn.recv(bufsize)
if recvdata:
update_clients(recvdata)
else:
break
except Exception as e:
print(e)
break
playermap.pop(player_id)
players.remove(conn)
conn.close()
# VARIABLES ------------------------------------------------------------------------------------------------------------ #
MAX_PLAYER_COUNT = 15
ipport = get_ip_port("serverip.txt")
s = socket.socket(socket.AF_INET,socket.soCK_STREAM)
s.bind(tuple(ipport))
s.listen(MAX_PLAYER_COUNT+1)
bufsize = 2048
global playermap
global players
players = []
playermap = {}
playerstartpos = [50,50]
print("Server has started,waiting for connections.")
#player key structure: {playerid:[[x,name]}
# SERVER LOOP ---------------------------------------------------------------------------------------------------------- #
while True:
conn,addr = s.accept()
print(f"Connection from {addr}")
players.append(conn)
playerid = len(players)
playermap[playerid] = [[playerstartpos[0],playerstartpos[1]],False,""]
conn.send(json.dumps({"id update": playerid}).encode())
pthread = threading.Thread(target=client_thread,args=[conn,playerid])
pthread.start()
# player key structure: {playerid:[[x,name]}
# update = {'player locations':[[value.id,value.x,value.y,value.flip,value.name]]}
ins,outs,ex = select.select([n.socket],[],0)
for in_ in ins:
data = in_.recv(2048)
print(data.decode() + "\n")
if data:
try:
socket_event = json.loads(data)
except Exception as e:
print(e)
event_type = [key for key in socket_event.keys()][0]
event_data_lst = socket_event[event_type]
if event_type == 'id update':
player.id = event_data_lst
if event_type == 'player locations':
#socket_event.pop(0)
players = []
for splayer in event_data_lst:
if splayer[0] != player.id:
socket_player = Player((splayer[1],splayer[2]),(15,37),splayer[4],splayer[0])
socket_player.flip = splayer[3]
players.append(socket_player)
#else:
# player.x = splayer[1]
# player.y = splayer[2]
解决方法
这可能是问题所在
for player_socket in players:
update = {'player locations':[]}
for key,value in playermap.items():
update['player locations'].append([key,value[0][0],value[0][1],value[1],value[2]])
try:
print(json.dumps(update).encode())
player_socket.sendall(json.dumps(update).encode())
所以基本上发生的是您从所有player_socket
发送,这应该没问题,但是当有两个播放器时,其中两个循环几乎并行运行,这意味着您从每个套接字发送了两次(希望理解),我应该做到这一点,以使此for
循环将发件人排除在外
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。