python 中的 UDP 广播和自动服务器发现,TCP 套接字不可用

UDP broadcast and automatic server discovery in python, TCP socket unavailable

我正在 python 中开发反向 shell 应用程序,现在我正在尝试实现自动发现功能。它应该按如下方式工作:

  1. 服务器广播 IP/port 它侦听连接,并等待客户端。如果几秒钟内没有客户端尝试连接,它会再次广播(并重复直到连接)。
  2. 客户端尝试接收服务器的广播,并连接到通告的IP/port。

广播工作正常,客户端收到 IP/port 并成功连接,但是在使用连接的端口对后我得到(服务器端):

socket.error: [Errno 35] Resource temporarily unavailable

服务器端测试代码:

sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sckt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sckt.settimeout(2)
sckt.bind(('', 9999))
sckt.listen(5)

broadcastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
while True:
    broadcastSocket.sendto(socket.gethostbyname(socket.getfqdn()) + ' ' + str(9999), ('<broadcast>', 8888))
    try:
        sock, address = sckt.accept()
        break
    except socket.timeout:
        pass
broadcastSocket.close()
sckt.settimeout(None)

sock.send('test')
# if I add time.sleep(1) here, it works, but I don't get why
# would sock be unavailable at first, but available a second later
print sock.recv(1) # this is where it fails
# note that it also fails with any recv buffer size, for instance 1024

您可能会问,我到底为什么要接收 1 个字节的数据。我有一个算法,它为消息加上长度前缀,接收方逐字节读取这个前缀,直到一个分隔符,这就是原因。 客户端测试代码:

broadcastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
broadcastSocket.settimeout(3)
broadcastSocket.bind(('', 8888))
while True:
    try:
        data = broadcastSocket.recv(1024)
        break
    except socket.timeout:
        pass
broadcastSocket.close()

sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sckt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sckt.connect((str(data.split()[0]), int(data.split()[1])))

print sckt.recv(1024)
sckt.send('lel')

如果我省略代码的整个广播和自动发现部分并简单地手动输入服务器 IP/port print sock.recv(1) 不会失败。 关于问题可能是什么的任何线索?

在服务器代码中将 sckt.settimeout(None) 更改为 sock.settimout(None)

您希望 accepted 套接字处于阻塞模式,而不是 accepting 套接字。

这确保 sckt.recv 等待来自客户端的传入消息。

P.S。 sock.setblocking(1)完全一样