当前位置: 首页 > 知识库问答 >
问题:

Python udp游戏服务器freezig

司徒池暝
2023-03-14

我正在尝试构建一个使用套接字和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, address1, 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())
 
 

我会解释里面的代码是做什么的。所以首先,它等待两个请求,并将它们放入lobby列表中。如果发出了两个请求,服务器将向客户端发送一个新端口,并创建一个具有两个线程的新进程。两个线程都在使用新端口,一个接收数据,另一个发送数据。我正在使用队列,这样我就可以跟踪数据,避免在相同的时间内使用相同的资源。客户端是一个pygame游戏。我做了一个小的测试游戏方块移动的地方,鼠标的位置。https://pastebin.com/qdku6rij.我有一个连接类,我把它放在游戏的init中。起初,我也使用多线程连接,但我观察到它运行得非常慢(我不认为这是线程错误,但我真的不知道)。因此,curent connection类与主服务器连接,等待发送端口,并用两个线程启动新进程:一个线程监听数据,另一个线程正在发送。我也在其中使用了一个队列,尽管多进程队列很慢。只是为了测试。

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, args = (sock, buffer_size,))
        self.thread2 = threading.Thread(target = send, args = (sock, 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, 0)
    green = (115, 198, 0)
    brown = (102, 51, 0)
    gray = (215, 218, 218)

这段代码的问题是,它会变得滞后,直到它完全冻结。一开始效果很好,但几秒钟后,方块看起来像是瞬移。我的猜测是可能是内存泄漏或我完全错误的东西,而不是真正的发送和接收的问题,因为我的方形也是滞后的,当程序冻结在那里,所以更多的打印从更新函数。一切都停止了。如果你知道为什么会这样,我会非常感激。我必须在本月30之前完成这个项目,我真的很迷茫,因为这个问题。任何建议都是很有帮助的!

共有1个答案

杨海
2023-03-14

我唯一能想到的就是两个while循环同时运行。检查您的线程并确保2个while循环不在同一线程上运行。

 类似资料:
  • 我试图建立一个通用服务器总是在连接的客户端。 该体系结构由4个主要组件组成 有状态应用服务器 无状态网关服务器 客户排队 系统和经纪人 工艺流程 客户端连接到网关 我正在使用JavaNetty作为网关。appserver也是用Java编写的。 我很想说这个设计像Mongrel2,但我不能完全确定。我想说,这更符合城市飞艇氦边缘服务器的设计(http://urbanairship.com/blog/

  • JAGS 游戏服务器是一个开源的 Java / AS 3.0 的游戏服务器,支持多玩家、碰撞检测以及键盘事件等等。

  • 二本鼠鼠学Java没出路。。 技术面 - 50min - 9.26 自我介绍 介绍一下你的项目经历 MySQL索引底层结构 Redis有哪些数据结构 Redis的持久化机制 学过其他语言吗(c++和go),说一下c++、go、Java的区别 LRU怎么实现 最短路径算法实现 JVM垃圾回收算法 手撕在一排数据中算出不重复数据的子集 TCP三次握手 你知道什么是SYN攻击吗 TCP四次挥手为什么是四

  • 过年回上海裸辞出去玩了一个月,5月回来找的工作,正好现在有时间了,抽空写一下社招面经,有些已经忘记了。裸辞还是太冲动了,菜鸡不配gap,两年工作经验不应该随便裸辞,还是太年轻、太狂妄了。当年校招腾讯、祖龙、小米等等offer随便拿,以为社招还跟校招一样简简单单,结果现在只能去个小公司养老了。 巨人网络(球球大作战) golang游戏后端,线下1、2、3面一起的 一面 项目架构图 pb的底层实现结构

  • 最后,是否可以重复使用相同的runnable(每个游戏会话1个),而不是每回合创建一个新的。

  • 我试图建立一个通用服务器总是在连接的客户端。 该体系结构由4个主要组件组成 有状态应用程序服务器 工艺流程 客户端连接到网关 我正在使用JavaNetty作为网关。appserver也是用Java编写的。 我很想说这个设计像Mongrel2,但我不能完全确定。我想说,这更符合城市飞艇氦边缘服务器的设计(http://urbanairship.com/blog/2010/08/24/c500k-in