【发布时间】:2018-03-26 21:10:08
【问题描述】:
是否可以通过多个线程在单个端口上与 TCP 套接字服务器进行通信,无论是共享一个公共套接字还是使用独立的套接字,而无需锁定机制或其他跨线程通信技术?
我的具体问题:
我是 python 套接字编程的初学者,正在尝试编写一个库来与联网的家庭自动化设备 (GlobalCache GC100) 接口
我需要通过 TCP 不断监听来自该硬件的传感器状态变化事件,并且能够在用户启动的时间发送 set_state 命令(跳闸继电器),而不会出现明显延迟。
我有一个while True:loop,它执行socket.recv() 来获取状态更改事件。大多数情况下,这会超时 (socket.settimeout(10)) 并继续下一个循环迭代,直到设备推送状态更改数据。
现在最重要的是,我需要用户能够发送 set_state 命令,并且我不希望用户需要等到 socket.recv() 超时并在 recv() 循环之间注入通信迭代。所以我选择使用它自己的套接字(但指向同一个主机和端口)将 tcp 监听循环分成一个单独的线程。
问题在于 set_state 线程中的套接字似乎杀死了侦听线程中的套接字,反之亦然。似乎只有最近创建/连接的套接字才真正起作用。
我是在尝试做一些通过套接字编程不可能做到的事情,还是这可能只是我设备上的套接字服务器实现的限制 (GC-100)?
到目前为止,我能看到的唯一解决方案是将所有套接字通信保持在一个线程中,使用一个公共套接字,实现一个通信队列,并将 tcp 侦听部分的超时持续时间保持在一个非常小的值,因此 set_state 命令必须在队列中等待最少的时间。但这似乎不太理想,而且有些脆弱。
编辑:
它是套接字对(由客户端 IP 组成的 4 元组 地址、客户端端口号、服务器 IP 地址和服务器端口 number) 指定唯一标识每个端点的两个端点 互联网中的 TCP 连接。 (TCP-IP 图解第 1 卷,W. 理查德·史蒂文斯)
我想也许我需要强制不同线程中的多个套接字使用的源端口有所不同。我尝试了socket.bind(hostname, source_port),但不断收到地址已在使用中的错误,对于所有似乎合理的主机名和源端口组合。
【问题讨论】:
-
单个 TCP 套接字完全能够同时发送/接收数据。
-
@bnaecker 我意识到我的描述并不能很好地说明具体问题,所以我对其进行了编辑。我的问题与通过一个或多个套接字同时在不同线程上与一个主机和端口进行通信有关。
-
用户如何向设备发送命令?如果通过文本/命令行界面之类的方式,您可以使用 IO 多路复用来处理单个套接字上的所有内容。查看
select或selectors模块,您可以无限期地等待,直到用户输入命令或设备发送状态更新。 -
另外,
socket.bind()调用仅在将接受传入连接的服务器中使用。听起来您有两个客户端套接字。其中每一个只需要调用connect()即可连接到设备。 -
@bnaecker 这是一个图书馆,例如,目前我做:
gc100 = GC100('192.168.1.100', 4998)gc100.start_listener(callback_fn_for_statechg_event)gc100.setstate(relay_id=1, state=0)
标签: python multithreading sockets tcp