【发布时间】:2023-02-10 19:37:20
【问题描述】:
我有一个通过 TCP 连接的工业机器人,它接收一个以字节为单位的字符串。我已经成功地在它们之间完成了一些简单的通信,但我现在需要添加另一个客户端,服务器可以在其中向任一客户端发送消息。我正在使用选择器,因为它有点抽象,我感到很困惑。
这是服务器代码 - 客户端是用 SPEL+ 编写的,所以我不会展示它,但非常非常简单 - 打印 [端口号] [消息]
import socket
import selectors
import types
import time
import queue
sel = selectors.DefaultSelector()
# # Any data received by this queue will be sent
# send_queue = queue.Queue()
def accept_wrapper(sock):
conn, addr = sock.accept() # Should be ready to read
fd = sock.fileno()
print(f"Accepted connection from {addr}, FD# {fd}")
conn.setblocking(False)
data = types.SimpleNamespace(addr=addr, inb=b"", outb=b"")
events = selectors.EVENT_READ | selectors.EVENT_WRITE
sel.register(conn, events, data=data)
def service_connection(key, mask, pending_messages):
sock = key.fileobj
data = key.data
print("Key.fd~~~~~~")
print(key.fd)
print("Key.fileobj.fileno()~~~~~~")
print(key.fileobj.fileno())
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024) # Should be ready to read
if recv_data:
data.outb += recv_data
else:
print(f"Closing connection to {data.addr}")
sel.unregister(sock)
sock.close()
if mask & selectors.EVENT_WRITE:
if len(pending_messages) > 0 and pending_messages[0][0] == key.fd:
print(pending_messages[0][0])
data.outb = pending_messages[0][1]
pending_messages.pop(0)
print(pending_messages)
if data.outb:
print(f"Echoing {data.outb!r} to {data.addr}")
sent = sock.send(data.outb) # Should be ready to write
data.outb = data.outb[sent:]
time.sleep(1)
def main(host, port):
#host, port = sys.argv[1], int(sys.argv[2])
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind((host, port))
lsock.listen()
print(f"Listening on {(host, port)}")
lsock.setblocking(False)
sel.register(lsock, selectors.EVENT_READ, data=None)
pending_messages = []
try:
while True:
events = sel.select(timeout=None)
for key, mask in events:
if key.data is None:
fd, addr = accept_wrapper(key.fileobj)
else:
pending_messages = [(fd, b"helloWorld\r")]
service_connection(key, mask, pending_messages)
except KeyboardInterrupt:
print("Caught keyboard interrupt, exiting")
finally:
sel.close()
if __name__ == '__main__':
main("",2000)
我认为 fd 是分配给选择器内连接的整数,另外(使用许多打印语句)我不确定选择器如何知道有数据要写入。 代码可能很熟悉,因为它来自 RealPython,但就像大多数教程一样,我发现它们都在服务器上停止,能够接受来自其他代码的消息,然后发送到客户端。
目前,我无法让多套接字服务器接受一条消息,然后将其发送给客户端。客户端和服务器确实进行通信,但这只是一个基本的回声。
【问题讨论】:
标签: python sockets tcp python-sockets