通过socketserver接收多条消息但发送一条消息

时间:2013-01-14 16:50:14

标签: python sockets pygame

A有两个线程的应用程序。它是一款网络控制游戏,

1。线程(服务器)

  • 接受套接字连接并接收消息
  • 发送消息时,创建一个事件并将其添加到队列

代码:

class SingleTCPHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        try:
            while True:
                sleep(0.06)
                message = self.rfile.readline().strip()              
                my_event = pygame.event.Event(USEREVENT, {'control':message})
                print message
                pygame.event.post(my_event)

2。线程(pygame)

  • 负责游戏渲染
  • 通过服务器填充的事件队列接收消息
  • 每60毫秒根据消息呈现游戏

这就是游戏的外观。控制信息只是小方块的速度。

enter image description here

出于调试目的,我使用以下命令从虚拟机连接到服务器:

ncat 192.168.56.1 2000

然后发送控制消息。在制作中,这些消息将由Android设备每50ms发送一次。

问题

在我的调试环境中,我手动输入几秒钟的消息。在我没有输入任何内容的时候,游戏会被渲染很多次。会发生的是message(在服务器代码中)不断使用先前接收的值进行渲染。

我发送以下内容:

1:0.5

在应用程序启动的控制台上,由于服务器代码中的行print message,我收到以下内容:

alan@alan ~/.../py $ python main.py 
1:0.5

游戏的作用是它不断地(它呈现的时间段,而不是我键入的每几秒钟)接收到这个值。

这是偶然的,我希望print message中的while True也能不断输出,输出结果为:

alan@alan ~/.../py $ python main.py 
1:0.5
1:0.5
1:0.5
1:0.5
....

然而事实并非如此。请告知(如果不够充分解释,我也愿意接受改变主题的建议)

1 个答案:

答案 0 :(得分:3)

你的while True循环正在轮询套接字,它只会在发送时收到消息;它不知道或不关心下游事件使用者正在对这些消息做什么,它只是每隔0.6秒为一个事件发送一个事件并在套接字队列上打印下一条记录的内容。如果您希望游戏在每个渲染循环中打印当前命令,则必须将print语句放在渲染循环中,而不是放在套接字轮询器中。此外,既然你似乎想让最后一个命令“坚持”并且不发布新事件,除非用户实际输入了一些内容,你可能想在套接字处理程序中的事件调度代码周围放一个if message:块在这里现在,如果用户自您上次检查后没有提供任何输入,您将每隔.6秒发送一个空事件。

我也认为在你的套接字处理程序中放置一个sleep或者你所拥有的循环可能是不可取的。 SocketServer每次在套接字上接收数据时都会调用它,这样就可以为你做有效的循环了,所有在这里做的就是打开你的溢出缓冲区,我认为。如果您想控制将事件发布到pygame的频率,您可能希望通过阻止某个类型的事件(如果已经排队1)来添加,或者通过从队列中获取给定类型的所有事件来实现游戏循环然后忽略除了第一个或最后一个之外的所有。您也可以通过检入处理程序来控制它,如果它已经发布了自上次事件发布以来的一段时间,但是您必须确保事件使用者能够处理具有多个事件的事件队列,并且在需要时进行适当的队列刷新。

编辑:

Docs

  

区别在于第二个处理程序中的readline()调用将多次调用recv(),直到遇到换行符,而第一个处理程序中的单个recv()调用将返回从第二个处理程序发送的内容。客户端在一个sendall()调用。

所以是的,读完整行都是有保障的。事实上,我认为try也不是必需的,因为除非有输入要处理,否则甚至不会调用它。