大家下午大家都在读这篇文章,我不熟悉使用套接字进行编程,也不熟悉异步编码(我觉得async可能是我问题解决方案的一部分),所以请原谅我犯下的任何愚蠢错误。
首先,我有一个UDP Echo服务器充当游戏服务器。无论什么时候发送ping都会发送给它,它会将源IP和端口添加到"连接的客户端列表中,并将该确切的ping发送给列表中的所有人,不包括发件人。这种方法效果很好,因为它会在收到消息时做出反应,所以它总能听到。然而,客户端的问题是我需要经常发送ping,同时还要倾听。
这是我的客户目前的样子:
import socket
from time import sleep
from contextlib import contextmanager
UDP_IP_ADDRESS = "127.0.0.1"
UDP_PORT_NO = 14004
Message = b"Hello World, From Client B"
@contextmanager
def socket_ctx():
""" Context Manager for the socket. Makes sure the socket will close regardless of why it exited."""
my_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Assign IP address and a RANDOM available port number to socket
my_socket.bind(('127.0.0.1', 0))
try:
# Let the rest of the app use the socket and wait for it to finish
yield my_socket
finally:
my_socket.close()
def send_data(client_sock):
client_sock.sendto(Message, (UDP_IP_ADDRESS, UDP_PORT_NO))
def listen(client_sock):
print(client_sock.recvfrom(100))
with socket_ctx() as sock:
while True:
send_data(sock)
listen(sock)
sleep(2)
目前,它发送一次ping,然后只是闲置,因为它可能正在侦听。如果它确实发生了ping回来,比如说,另一个客户端向服务器发送ping,并且服务器将ping发送到该客户端,它会听到它,打印它,然后再次启动循环。问题是,如果没有其他客户发送一些内容来震撼这一个,它就不会发送它。
我认为async可能是我的解决方案,但我不知道该怎么做。有没有人有这个问题的解决方案?
答案 0 :(得分:1)
以下是我如何使用“接收和处理传入的UDP套接字,以及每秒执行一次数据包发送”行为来实现服务器。请注意,这使用select()
函数来复用两个任务,而不是异步I / O;希望这没关系。
import socket
import select
import time
UDP_IP_ADDRESS = "127.0.0.1"
UDP_PORT_NO = 14004
Message = b"Hello World, From Client B"
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.bind(('127.0.0.1', 0))
print "UDP socket is listening for incoming packets on port", udp_socket.getsockname()[1]
# When we want to send the next periodic-ping-message out
nextPingTime = time.time()
while True:
secondsUntilNextPing = nextPingTime - time.time();
if (secondsUntilNextPing < 0):
secondsUntilNextPing = 0
# select() won't return until udp_socket has some data
# ready-for-read, OR until secondsUntilNextPing seconds
# have passed, whichever comes first
inReady, outReady, exReady = select.select([udp_socket], [], [], secondsUntilNextPing)
if (udp_socket in inReady):
# There's an incoming UDP packet ready to receive!
print(udp_socket.recvfrom(100))
now = time.time()
if (now >= nextPingTime):
# Time to send out the next ping!
print "Sending out scheduled ping at time ", now
udp_socket.sendto(Message, (UDP_IP_ADDRESS, UDP_PORT_NO))
nextPingTime = now + 1.0 # we'll do it again in another second