A имеют приложение с двумя потоками. Его сетевая управляемая игра,
1. thread (Server)
Код:
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)
Так выглядит игра. Управляющие сообщения - это просто скорости для маленького квадрата.
Для отладки я подключаюсь к серверу с виртуальной машины с помощью:
ncat 192.168.56.1 2000
Затем отправьте контрольные сообщения. В производстве эти сообщения будут отправляться каждые 50 мс на Android-устройство.
Проблема
В моей среде отладки я вручную печатаю сообщения с периодом в несколько секунд. За время я ничего не набираю, игра получается многократно. Случается, что message
(в коде сервера) постоянно отображается с ранее полученным значением.
Я посылаю следующее:
1:0.5
На консоли, на которой запущено приложение, я получаю следующее сообщение из print message
в коде сервера:
alan@alan ~/.../py $ python main.py
1:0.5
То, что делает игра, это действие, поскольку оно постоянно (с периодом, который он отображает, и не каждые несколько секунд, когда я набираю), получая это значение.
SInce, что произойдет, я ожидаю, что print message
которое находится в while True
также выводит постоянно и что выход:
alan@alan ~/.../py $ python main.py
1:0.5
1:0.5
1:0.5
1:0.5
....
Однако это не так. Просьба сообщить (я также открыт для предложений, чтобы сменить тему, если она недостаточно объяснительна)
Ваш while True
loop производит опрос сокета, который будет получать сообщения только при их отправке; он не знает и не заботится о том, что делает пользователь потока вниз по течению с этими сообщениями, он просто отправит событие и распечатает содержимое следующей записи в очереди на сокеты каждые 0,6 секунды. Если вы хотите, чтобы игра печатала текущую команду в каждом цикле рендеринга, вам придется поместить оператор print
в цикл рендеринга, а не в poller-сокет. Кроме того, поскольку вы, похоже, хотите, чтобы последняя команда "приклеивалась" и не отправляла новое событие, если пользователь не вводит что-либо, вам может понадобиться поместить if message:
блокировать код отправки события в обработчике сокетов, который у вас есть здесь, Прямо сейчас, вы будете отправлять пустое событие каждые 0,6 секунды, если пользователь не предоставил вам никакого ввода с момента последнего проверки.
Я также не думаю, что, вероятно, рекомендуется sleep
или цикл, который у вас есть, в вашем обработчике сокетов. SocketServer
будет вызывать его каждый раз, когда вы получаете данные в сокете, так что цикл эффективно выполняется для вас, и все, что делает это здесь, - это открыть вас, чтобы переполнить буфер, я думаю. Если вы хотите контролировать, как часто вы отправляете события в pygame, вы, вероятно, захотите сделать это, либо заблокировав события определенного типа, либо добавив их, если они уже поставлены в очередь, либо, захватив все события заданного типа из очереди каждый а затем просто игнорирует все, кроме первого или последнего. Вы также можете контролировать это, проверив обработчик, если это было некоторое количество времени с момента последнего опубликованного события, но тогда вы должны убедиться, что потребитель событий способен обрабатывать очередь событий с несколькими событиями, ожидающими на нем, и делает соответствующую очистку очереди при необходимости.
Редактировать:
Разница в том, что вызов readline() во втором обработчике будет вызывать recv() несколько раз, пока он не встретит символ новой строки, в то время как единственный вызов recv() в первом обработчике просто вернет то, что было отправлено клиентом в одном sendall().
Так что да, чтение всей строки гарантировано. На самом деле, я не думаю, что try
необходима, так как это даже не будет вызвано, если не будет ввода для обработки.