Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多人游戏中的Pygame和socket:OverflowError_Python_Python 3.x_Multithreading_Sockets_Pygame - Fatal编程技术网

Python 多人游戏中的Pygame和socket:OverflowError

Python 多人游戏中的Pygame和socket:OverflowError,python,python-3.x,multithreading,sockets,pygame,Python,Python 3.x,Multithreading,Sockets,Pygame,我正在尝试使用pygame和socket模块在Python中创建一个简单的多人游戏。它只是由两个圆圈组成,由两台不同计算机的W、A、S、D键控制 起初,我在PyGod循环的中间创建了一个带有 ReVo()/Client的客户端。它工作得很好,但是recv()阻塞了环路,因此圆圈的移动不平稳,我必须将速度增加到6(在设置为0.6之前),以获得正常速度。这是代码(我已经对其进行了一些总结): 客户端第1版 然后,我尝试将recv()放在一个线程中,以停止阻塞循环: 客户端第二版 但是,当我在两台不同

我正在尝试使用
pygame
socket
模块在Python中创建一个简单的多人游戏。它只是由两个圆圈组成,由两台不同计算机的W、A、S、D键控制

起初,我在PyGod循环的中间创建了一个带有<代码> ReVo()/Client的客户端。它工作得很好,但是

recv()
阻塞了环路,因此圆圈的移动不平稳,我必须将速度增加到6(在设置为0.6之前),以获得正常速度。这是代码(我已经对其进行了一些总结):

客户端第1版 然后,我尝试将
recv()
放在一个线程中,以停止阻塞循环:

客户端第二版 但是,当我在两台不同的计算机上启动客户机2的两个实例时,它会给我一个
溢出错误

溢出错误:Python int太大,无法转换为C long

我为范围(30)中的I添加了
,因为我认为服务器正在崩溃,因为同时发送的消息太多了。输出是相同的:大约3秒钟后,程序崩溃,出现
溢出错误

在两个版本中,我都在
recv()
之后添加了
print()
语句,以查看我接收到的x和y的值。在第1个版本中,它们都在宽度和高度范围内。然而,在第二个版本中,收到的消息中有1/5是一个大数字,例如
124381473265
。如果此数字更大,则会出现
溢出错误。我不明白为什么会发生这种情况:我在两个版本中以相同的方式编码和解码消息,但一个有效,另一个无效

我没有包括服务器代码,因为我认为没有必要。它只是在两个客户端之间传输消息,而不修改它们。服务器没有出现错误,因为在第一个客户端版本中,消息的发送和接收都是正确的

任何帮助都将被告知。如果你需要关于任何一点的更多信息,请告诉我


提前谢谢

将套接字代码放入线程,或使用
select.select()
进行非阻塞套接字读取。然后,当数据报从服务器到达时,将自定义事件消息发回主循环

import pygame
import enum

class NetworkEvents( enum.IntEnum ):
    EVENT_HANGUP    = pygame.USEREVENT + 1
    EVENT_MESSAGE   = pygame.USEREVENT + 2
您的套接字读取代码也应该处理部分数据包、挂起和延迟。我认为你上面的错误是由于试图打开一个部分(或某种程度上是垃圾)数据包造成的。人们通常使用
pickle
模块来封装这些数据,但首先,我会使用简单的字符串数据进行预测试。它更容易调试。然后,一旦传输代码全部固定下来并经过测试,如有必要,将其更改为二进制

我喜欢在套接字代码中使用
select()。它提供了对套接字的细粒度控制

下面是一个简单的线程套接字对话处理程序。它实际上只支持套接字挂起和传入消息。但它可以很容易地扩展以处理更多的消息类型

import threading
import pygame
import random
import enum
import socket
import select
import time

class ConversationHandlerThread( threading.Thread ):
    """ A thread that handles a conversation with a single remote server.
        Accepts commands of 'close', 'red', 'green' or 'blue', and posts messages
        to the main PyGame thread for processing """
    def __init__( self, server_address, server_port ):
        threading.Thread.__init__(self)
        self.server_address = server_address
        self.server_port    = server_port
        self.server_socket  = None
        self.data_buffer    = ''
        self.daemon         = True # exit with parent
        self.done           = False

    def stop( self ):
        self.done = True

    def connect( self ):
        self.server_socket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
        while True:
            try:
                self.server_socket.connect( ( self.server_address, self.server_port ) )
                print( "Connected to %s:%d" % ( self.server_address, self.server_port ) )
                break;
            except:
                print( "Failed to connect %s:%d" % ( self.server_address, self.server_port ) )
                time.sleep( 12 )
                print( "Retrying..." )

    def run( self ):
        """ Connects to Server, then Loops until the server hangs-up """
        self.connect()

        # Now we're connected, start reading commands
        read_events_on   = [ self.server_socket ]
        while ( not self.done ):
            # Wait for incoming data, or errors, or 0.3 seconds
            (read_list, write_list, except_list) = select.select( read_events_on, [], [], 0.5 )

            if ( len( read_list ) > 0 ):
                # New data arrived, read it
                incoming = self.server_socket.recv( 8192 )
                if ( len(incoming) == 0):
                    # Socket has closed
                    new_event = pygame.event.Event( NetworkEvents.EVENT_HANGUP, { "address" : self.server_address } )
                    pygame.event.post( new_event )
                    self.server_socket.close()
                    self.done = True
                else:
                    # Data has arrived
                    try:
                        new_str = incoming.decode('utf-8')
                        self.data_buffer += new_str
                    except:
                        pass # don't understand buffer

                    # Parse incoming message (trivial parser, not high quality) 
                    # commands are '\n' separated
                    if (self.data_buffer.find('\n') != -1 ):
                        for line in self.data_buffer.split('\n'):
                            line = line.strip()
                            # client disconnect command
                            if ( line == 'close' ):
                                new_event = pygame.event.Event( NetworkEvents.EVENT_HANGUP, { "address" : self.server_address } )
                                pygame.event.post( new_event )
                                self.server_socket.close()
                                self.done = True

                            # only make events for valid commands
                            elif ( line in ( 'red', 'green', 'blue' ) ):
                                new_event = pygame.event.Event( NetworkEvents.EVENT_MESSAGE, { "address" : self.server_address, "message" : line  } )
                                pygame.event.post( new_event )
                        self.data_buffer = ''  # all used-up
把所有这些复杂的东西放到一个线程中的美妙之处在于,一旦它开始了,你就可以忘记它

# Start the network-handler thread
thread1 = ConversationHandlerThread( '127.0.0.1', 5555 )
thread1.start()
在主循环中,像处理其他事件一样处理事件:

for event in pygame.event.get():
    if ( event.type == pygame.QUIT ):
        done = True

    elif ( event.type == NetworkEvents.EVENT_HANGUP ):
        print(" CLIENT DISCONNECTED %s " % ( str(event.address) ) )

    elif ( event.type == NetworkEvents.EVENT_MESSAGE ):
        print(" CLIENT MESSAGE FROM %s - %s " % ( str(event.address), event.message ) )
        if ( event.message == 'red' ):
            new_sprite = AlienSprite( RED )
            SPRITES.add( new_sprite )
# Start the network-handler thread
thread1 = ConversationHandlerThread( '127.0.0.1', 5555 )
thread1.start()
for event in pygame.event.get():
    if ( event.type == pygame.QUIT ):
        done = True

    elif ( event.type == NetworkEvents.EVENT_HANGUP ):
        print(" CLIENT DISCONNECTED %s " % ( str(event.address) ) )

    elif ( event.type == NetworkEvents.EVENT_MESSAGE ):
        print(" CLIENT MESSAGE FROM %s - %s " % ( str(event.address), event.message ) )
        if ( event.message == 'red' ):
            new_sprite = AlienSprite( RED )
            SPRITES.add( new_sprite )