通过socketserver接收多个消息但只发送一个
我有一个应用程序,它有两个线程。这是一个网络控制的游戏。
1. 线程(服务器)
- 接受socket连接并接收消息
- 当发送消息时,创建一个事件并将其添加到队列中
代码:
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毫秒根据消息渲染游戏
这就是游戏的样子。控制消息只是小方块的速度。
为了调试,我从虚拟机连接到服务器,使用:
ncat 192.168.56.1 2000
然后发送控制消息。在实际运行中,这些消息将由Android设备每50毫秒发送一次。
问题
在我的调试环境中,我手动输入消息,间隔几秒钟。在我不输入任何内容的时间里,游戏会被渲染很多次。发生的情况是,message
(在服务器代码中)不断用之前接收到的值进行渲染。
我发送了以下内容:
1:0.5
在启动应用程序的控制台上,我由于服务器代码中的print message
收到以下内容:
alan@alan ~/.../py $ python main.py
1:0.5
游戏的表现就像是它不断(以渲染的周期,而不是我每几秒输入一次)接收到这个值。
由于这种情况,我本以为while True
中的print message
也会不断输出,并且输出应该是:
alan@alan ~/.../py $ python main.py
1:0.5
1:0.5
1:0.5
1:0.5
....
然而事实并非如此。请给我建议(如果主题不够清晰,我也欢迎提出更改建议)
1 个回答
你的 while True
循环在不停地检查这个“插座”,它只会在有消息发送过来的时候才会得到信息;它并不知道或者不关心后面的事件处理程序在对这些消息做什么。它每0.6秒就会处理一个事件,并打印出插座队列中下一个记录的内容。如果你想让游戏在每次渲染循环中都打印当前的命令,你需要把 print
语句放在渲染循环里,而不是放在插座的检查部分。另外,既然你似乎想让最后一个命令“保持”,而不是在用户没有输入新内容时就发送新事件,你可能需要在你这里的插座处理程序中把事件分发的代码放在一个 if message:
的判断块里。现在,如果用户自上次检查以来没有提供任何输入,你每0.6秒就会发送一个空事件。
我觉得在你的插座处理程序里放一个 sleep
,或者你现在的循环,可能不是个好主意。因为 SocketServer
每次接收到插座上的数据时都会调用这个处理程序,所以这个循环实际上是由系统帮你处理的。这样做只会让你面临缓冲区溢出的风险。如果你想控制向pygame发送事件的频率,可能需要通过阻止某种类型的事件被添加(如果已经有一个在排队的话),或者在每个游戏循环中从队列中获取所有特定类型的事件,然后只处理第一个或最后一个。你也可以通过在处理程序中检查自上次事件发布以来是否经过了一段时间来控制,但这样你需要确保事件处理程序能够处理有多个事件在等待的事件队列,并在需要时进行适当的队列清理。
编辑:
文档:
区别在于,第二个处理程序中的 readline() 调用会多次调用 recv(),直到遇到换行符,而第一个处理程序中的单个 recv() 调用只会返回客户端在一次 sendall() 调用中发送的内容。
所以,是的,读取整行是有保证的。实际上,我觉得 try
也不是必要的,因为只有在有输入需要处理时才会调用这个。