Skip to main content
 首页 » 编程设计

python之专有协议(protocol)(Python、select、epoll)的长生命周期多线程客户端

2025年05月04日30wuhuacong

首先,我潜伏了很长时间但第一次使用,我要感谢大家创建这个网站!

我现在需要实现专有协议(protocol)的客户端部分。该协议(protocol)底层使用 TCP/IP,消息流可概括如下:

  1. 客户端连接到服务器
  2. 客户表示对某种类型的数据感兴趣
  3. 如果服务器有任何这样的数据,它会向下发送给客户端
  4. 客户端向服务器确认接收
  5. 客户端现在需要告诉服务器它仍然对相同类型的数据感兴趣
  6. 服务器将传入的数据发送给客户端
  7. 客户端需要时不时(比如每分钟左右)向服务器发送应用级的保活请求
  8. 有些来自服务器的消息需要客户端向服务器发回回复
  9. 客户端断开连接

所有这些都将在单个 TCP session 中发生,这是一个长期存在的 session ,有点像我想象的 WebSocket。

还有一点就是客户端要部署在多线程服务器上,应该允许多个线程并发访问,这意味着单个线程应该能够“订阅”来自服务器的某种类型的消息服务器,并且还应该能够向其发送消息。

我很了解 GIL,因此我想对此没有太多评论,我只是在编写一个客户端,我不能更改架构的任何其他部分。

所以问题是我从来没有深入研究过 HTTP 级别,我很幸运总是使用一些已经存在的库,另一方面,我没有做过那么多的网络编程,那这将是我第一次成为那样的人。

我希望这是一个让我了解所有异步库/工具/工具包(如 select、epoll、libev 或 gevent)的机会。

问题是网络上的大部分资源都与编写服务器有关,我什至不确定我是否要在多线程上部署客户端并不意味着它们都不会做很多。所有服务器人员显然都是单线程的,但不清楚是因为不需要多线程还是因为 epoll 之类的东西不太喜欢使用它们的多线程。

服务器显然将所有客户端视为单线程单元,因此我认为我需要序列化对客户端的访问。我不太明白的是如何确保服务器响应与线程匹配,反之亦然。如果一个线程收到一条消息,但另一个线程需要在前一个线程有机会确认消息之前确认它收到的消息,那么我如何才能确保消息不会混淆?

你怎么看待这一切?在这种情况下,异步库是一个不错的选择吗?你能想到我可以看看的任何代码示例吗?我正在使用 Python,但我认为这个问题足够通用,我可以使用 C、C++ 或 Java 来获得灵感。

非常非常感谢!

请您参考如下方法:

每个线程(每个客户端)是否可以打开自己的套接字?在那种情况下,一切都不是问题:只有那个线程中的客户端拥有该套接字的句柄,因此它会自动从服务器获取正确的数据。对于服务器来说,所有这些来自客户端的连接看起来都像是完全独立的客户端连接(这正是它们的本来面目)。

如果其中一个要求是限制网络连接的总数,那么你可以构造一个特殊的线程来维护与服务器的连接,并在本地接收来自各种线程的通信请求/但是使用独立的套接字(一个每个线程)可能要简单得多。

您一定要使用应用程序级别的保活吗?因为 TCP 可以自动为你做这件事。如果没有及时收到 keepalive,则套接字将关闭,从而通知另一方连接已超时。如果您的情况可行,请考虑将此作为一个选项。

最后,如果您不必执行应用程序级别的保活,则可以利用多线程编程的优点之一:开发每个线程,就好像它是唯一的线程一样,然后您就不需要了根本不需要担心任何异步的事情。例如,您可以编写客户端以发送请求然后阻塞-等待响应,进行计算并发送结果或检查是否有来自服务器的更多数据到达。来自服务器的数据将累积在您这边的 TCP 接收窗口中。这也作为流量控制的一种方式:如果您的客户端变得太慢并且接收窗口已满,那么服务器将无法再发送。这可能会阻塞服务器,因此您需要查看服务器是否可以处理这种情况。