如何解决Python udp游戏服务器冻结
我正在尝试使用套接字和 udp 协议构建一个 python 在线游戏。 我创建了一个多处理和多线程服务器:https://pastebin.com/ZucxWPC9。
import socket
import multiprocess
def new_lobby(port,addr1,addr2):
import socket
import Queue
import threading
address1 = addr1
address2 = addr2
local_ip = ""
local_port = port
buffer_size = 1024
print(port)
sock = socket.socket(family = socket.AF_INET,type = socket.soCK_DGRAM)
sock.bind((local_ip,local_port))
sock.settimeout(10)
running = True
q = Queue.Queue(10000)
print ("before threads")
def listen(sock):
running = True
buffer_size = 1024
while running:
try:
data_address = sock.recvfrom(buffer_size)
except socket.timeout:
running = False
q.put(data_address)
def send(sock,address1,address2):
while True:
data_address = q.get()
if data_address[1] == address1:
sock.sendto(data_address[0],address2)
else:
sock.sendto(data_address[0],address1)
thread1 = threading.Thread(target = listen,args=(sock,))
thread2 = threading.Thread(target = send,args = (sock,address2))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
local_ip = ""
local_port = 10001
buffer_size = 1024
server_message = "connected"
byte_server_message = str.encode(server_message)
sock = socket.socket(family = socket.AF_INET,type = socket.soCK_DGRAM)
sock.bind((local_ip,local_port))
lobby = []
port_count = 10002
check_alive = False
while True:
message,address = sock.recvfrom(buffer_size)
message = message.decode("utf-8")
print(address," ",message)
if address not in lobby:
lobby.append(address)
if len(lobby) == 2:
p = multiprocess.Process(target = new_lobby,args = (port_count,lobby[0],lobby[1]))
p.start()
port = str(port_count)
port = port.encode()
for address in lobby:
print(address)
sock.sendto(port,address)
port_count += 1
lobby = []
check_alive = True
if check_alive:
print(p.is_alive())
我会解释里面的代码是做什么的。所以首先它等待两个请求并将它们放在大厅列表中。如果发出了两个请求,服务器会向客户端发送一个新端口并创建一个具有两个线程的新进程。两个线程都在使用新的端口,一个接收数据,另一个发送数据。我正在使用队列,因此我可以跟踪数据并避免同时使用相同的资源。 客户端是一个pygame游戏。我制作了这个小方块测试游戏,它可以在鼠标位置所在的位置移动。 https://pastebin.com/QdKU6Rij。我有一个连接类,我把它放在游戏的初始化中。起初我也使用多线程进行连接,但我发现它运行得很慢(我现在不认为这是线程错误,但我真的不知道)。因此,当前连接类与主服务器连接,等待发送端口并启动一个具有两个线程的新进程:一个侦听数据,一个正在发送。即使多进程队列很慢,我也在那里使用了一个队列。仅用于测试目的。
import socket
import json
import queue
import threading
import sys
#f = find lobby
pygame.init()
class Connection():
def __init__(self):
self.msgFromClient = "f"
self.bytesToSend = str.encode(self.msgFromClient)
self.serverAddressport = ("",10001)
self.bufferSize = 10000
self.sock = socket.socket(family=socket.AF_INET,type=socket.soCK_DGRAM)
self.sock.setblocking(0)
self.sock.sendto(self.bytesToSend,self.serverAddressport)
self.msgFromServer = self.sock.recvfrom(self.bufferSize)
self.msg = self.msgFromServer[0]
self.port = self.msg.decode("utf-8")
self.port = int(self.port)
self.serverAddressport = ("",self.port)
self.q_listen = queue.Queue(1000)
self.q_send = queue.Queue(1000)
def listen(sock,buffer_size):
running = True
while running:
data_address = sock.recvfrom(buffer_size)
data = data_address[0].decode("utf-8")
data = json.loads(data)
self.q_listen.put(data)
def send(sock,serverAddressport):
running = True
while running:
data = self.q_send.get()
if data:
data = json.dumps(data)
data = bytes(data,'utf-8')
sock.sendto(data,serverAddressport)
sock = self.sock
buffer_size = self.bufferSize
serverAddressport = self.serverAddressport
self.thread = threading.Thread(target = listen,buffer_size,))
self.thread2 = threading.Thread(target = send,serverAddressport))
self.thread.daemon = True
self.thread2.daemon = True
self.thread.start()
self.thread2.start()
import global_variables as g
#de sters,o sa fie initializat in main game
g.screen = pygame.display.set_mode([1800,900])
class Player(pygame.sprite.Sprite):
def __init__(self,color):
pygame.sprite.Sprite.__init__(self)
self.size = 60
self.image = pygame.Surface((self.size,self.size))
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.center = (400,400)
def Blit(self,screen):
screen.blit(self.image,self.rect)
class Test_Game():
def __init__(self):
g.variables_initialization()
self.surface_size = g.surface_size
self.surface = pygame.Surface((self.surface_size,self.surface_size))
self.surface_rect = self.surface.get_rect()
self.surface_rect.center = (800,450)
self.running = True
self.player = Player(g.brown)
self.player2 = Player(g.green)
self.connection = Connection()
def Blit_Images(self):
g.screen.fill(g.white)
self.surface.fill(g.black)
self.player.Blit(self.surface)
self.player2.Blit(self.surface)
g.screen.blit(self.surface,self.surface_rect)
pygame.display.flip()
def Update(self):
dt = g.clock.tick(60) / 1000
pos = pygame.mouse.get_pos()
self.player.rect.centerx = pos[0] - 400
self.player.rect.centery = pos[1] - 50
coord = (self.player.rect.centerx,self.player.rect.centery)
self.connection.q_send.put(coord)
self.player2.rect.center = self.connection.q_listen.get()
def Check_Events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
def Loop(self):
while self.running == True:
self.Check_Events()
self.Update()
self.Blit_Images()
test_game = Test_Game()
test_game.Loop()
其中还有一个用于全局变量的文件(以防您想运行代码):https://pastebin.com/RhDwjeKQ
import pygame
def variables_initialization():
global clock
global dt
global screen
global surface_size
global white
global black
global green
global brown
global gray
clock = pygame.time.Clock()
dt = 0
surface_size = 800
white = (250,250,250)
black = (0,0)
green = (115,198,0)
brown = (102,51,0)
gray = (215,218,218)
这段代码的问题在于它在完全冻结之前会变得滞后。起初它真的很好用,但几秒钟后,方块看起来像是传送了。我的猜测是可能存在内存泄漏或我完全误用的东西,而不是发送和接收的真正问题,因为我的方块也很滞后,当程序冻结时,更新功能也会进行更多打印。一切都停止了。 如果您知道为什么会发生这种情况,我将不胜感激。我必须在这个月 30 之前完成这个项目,因为这个问题我真的很迷茫。任何建议都非常有帮助!
解决方法
我唯一能想到的就是同时运行 2 个 while 循环。检查您的线程并确保 2 个 while 循环不在同一线程上运行。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。