首页 > 解决方案 > 线程写入顺序

问题描述

我正在尝试使用 pygame 制作多客户端游戏。我正在尝试测试客户端向服务器发送数据和服务器发送广播消息的功能,以便所有客户端都可以看到精灵位置。我实现了一个较小的测试样本,其中一些方块移动,这个样本的目的是测试客户端更新从服务器接收到的数据(屏幕上方块的位置)。背后的想法是客户端从初始位置发送更改位置,服务器处理数据并将其发送回单个消息中,如 |1|100|100|2|200|200|3|300|300 等等,以 1当时是第一个位置为 100 和 100 的客户,2 是第二个客户,依此类推。我将留下测试样本:

服务器.py:

import socket,time,threading
playersNo = 0
counter = 0
message = ""
messageList = {}

def on_new_client(clientsocket,addr):
    global message, counter, playersNo, messageList
    while True: 
        time.sleep(0.016)
        counter +=1
        changeX = clientsocket.recv(1024).decode()
        splitChange=changeX.split()
        #process the data
        toSendY, toSendX=processData(splitChange[1], splitChange[0],splitChange[2],splitChange[3])
        #Send message
        message=str(toSendY)+"|"+str(toSendX)+"|"
        if ( counter >= (playersNo+1) ):
            counter = 1
        messageList[str(counter)]=message
        changesBackToClient = str(toSendY)+' ' + str(toSendX)
        clientsocket.send(changesBackToClient.encode())
    clientsocket.close()

def broadcast_message(messageList):
    
    server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 
    server.settimeout(0.2)
 
    while True:
        message=""
        for k,v in messageList.items():
            message+= k +"|"+v+"|"
        message = bytes(message, 'utf-8')
        server.sendto(message, ('<broadcast>', 37020))
        time.sleep(0.015)
    
def tcp_socket():
    global playersNo,messageList
    host = socket.gethostname()
    port = 5000  

    server_socket = socket.socket()  
    server_socket.bind((host, port))  
    server_socket.listen(4)
    server_socket.settimeout(0.1)
    
    while True:  
        try:
            conn, address = server_socket.accept()
            playersNo+=1
            t = threading.Thread(target = on_new_client, args =(conn,address,))       
            t.start()      
            
        except socket.timeout:
            continue
        
    server_socket.close()   
                 
def processData(changeX, changeY,initialValX, initialValY):
    dataY = int(initialValY) + int(changeY)
    dataX = int(initialValX) + int(changeX)
    return dataY, dataX

if __name__ == '__main__':
    thrd = threading.Thread(target=broadcast_message,args = (messageList,))   
    thrd.start()
    tcp_socket()

客户端.py:

import pygame,socket,threading,time,random

data=" "

screen_width = 1280
screen_heigth = 960

sqXChange = 0
sqYChange = 0

class Square:
    def __init__(self, color,left, top ):
        self.color= color
        self.left = left
        self.top = top

    def draw(self):
        pygame.draw.rect(screen, self.color,(self.left,self.top,50,50))
  
sq1 = Square((255,40,0), random.randint(0,1000),random.randint(0,800))  

def gameLoop():
    global sqXChange, sqYChange, sq1
    
    running = True

    while running:
        screen.fill((255,255,255))
        sq1.draw()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False      
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    sqYChange -=5
                    
                elif event.key == pygame.K_RIGHT:
                    sqYChange +=5
                    
                elif event.key == pygame.K_UP:
                    sqXChange -=5
                    
                elif event.key == pygame.K_DOWN:
                    sqXChange +=5
                    
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    sqXChange=0
                    sqYChange=0

        pygame.display.flip()
        clock.tick(60)

def tcp_socket():
    global sqXChange,sqYChange, sq1,data
    host = socket.gethostname()  
    port = 5000  

    client_socket = socket.socket()  
    client_socket.connect((host, port)) 
    while True:
        time.sleep(0.016)
        changes = str(sqXChange)+' '+str(sqYChange) +' ' + str(sq1.left) +' ' + str(sq1.top) 
        client_socket.send(changes.encode())  
        
        changeFromServer = client_socket.recv(1024).decode().strip().split()
        print(data)
        
        sq1.top = int(changeFromServer[0])
        sq1.left = int(changeFromServer[1])
        
    client_socket.close()  

def broadcast_message():
    global data
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # UDP
    client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    client.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    client.bind(("", 37020))
    
    while True:
        time.sleep(0.016)
        data,addr = client.recvfrom(2048)
        data.decode()
        
if __name__ =="__main__":   

    pygame.init()
    clock = pygame.time.Clock()

    screen = pygame.display.set_mode((screen_width,screen_heigth))
    t1 = threading.Thread(target = broadcast_message)
    t2 = threading.Thread(target = tcp_socket)
    t1.setDaemon(True)
    t2.setDaemon(True)
    
    t2.start()
    t1.start()

    gameLoop()

我是 pygame 和线程的新手,所以代码可能有点乱。我现在的问题是数据有时是由 1|100|100|2|200|200 (好的位置)发送的,有时它会根据线程写入 1|200|200|2|100|100 (错误的位置)在那一刻写作。我该如何解决?提前致谢

标签: pythonmultithreadingpygame

解决方案


推荐阅读