【问题标题】:Writing a server application that Pushes to clients (TCP)编写推送到客户端 (TCP) 的服务器应用程序
【发布时间】:2011-11-01 00:39:49
【问题描述】:

我正在编写一个客户端-服务器应用程序,其中一个要求是服务器在收到来自其中一个客户端的更新后,能够将新数据推送到所有其他客户端。这是一个 C++ (Qt) 应用程序,旨在在 Linux(客户端和服务器)上运行,但我更多的是寻找关于它应该如何工作的高级概念想法(尽管低级想法也很好)。

服务器:

它需要(在它的其他职责中)保持一个套接字打开,监听来自可能 n 个不同客户端的传入数据包,大概是在后台线程上(我没有写太多关于套接字代码的内容)除了学校里的一些 rinky-dink 例子)。从客户端获取这些数据后,它会对其进行处理,然后将其发送给所有客户端,对吧?

当然,我不确定它实际上是如何做到的。我猜这意味着它必须与每个客户端(至少是活动客户端)保持持久连接,但我什至从概念上不明白如何维护这个连接(或这些连接的列表)。

那么,我应该如何处理呢?

【问题讨论】:

  • 最好将 TCP 连接视为数据流,而不是 数据包

标签: c++ qt sockets client-server push


【解决方案1】:

一般来说,当您有多个客户端时,有几种方法可以处理此问题。

首先,在 TCP 中,当客户端连接到您时,它们会被放入队列中,直到它们可以被服务为止。这是给定的,除了调用accept 系统调用来接收新客户端之外,您不需要做任何事情。收到客户端后,您将获得一个用于读取和写入的套接字。谁先读/写完全取决于你的协议,但双方都需要知道协议(由你定义)。

获得套接字后,您可以做一些事情。在一个简单的情况下,您只需读取一些数据,处理它,写回套接字,关闭套接字,然后为下一个客户端提供服务。不幸的是,这意味着您一次只能为一个客户提供服务,因此不可能进行“推送”更新。另一种策略是保留所有打开的套接字的列表。任何“更新”只需遍历列表并写入每个套接字。不过这可能会带来问题,因为它允许推送更新(如果客户端发送了请求,谁会关注它?)

更高级的方法是为每个套接字分配一个线程。在这种情况下,每次创建套接字时,都会启动一个新线程,其全部目的是为一个客户端提供服务。这减少了延迟并利用了多个内核(如果可用),但编程难度要大得多。此外,如果您有 10,000 个客户端连接,那么 10,000 个线程就太多了。将更新推送到单个客户端(在这种情况下)非常简单(线程只是写入其各自的套接字)。一次推送到所有这些有点棘手(需要线程事件或生产者/消费者队列,实现起来都不是很有趣)

当然,还有一百万种其他方法可以处理这个问题(每个客户端一个进程、一个线程池、一个负载平衡代理,等等)。只要说没有办法在一个答案中涵盖所有这些就足够了。我希望这能回答您的基本问题,如果您需要我澄清任何事情,请告诉我。这是一个很大的课题。但是,如果我可以提出建议,处理多个客户是一个被重新发明了一百万次的轮子。那里有非常好的库,它们比原始套接字 IO 更高效且对程序员更友好。我建议libevent,它将网络请求变成了事件驱动的范例(更像是 GUI 编程,这可能对你有好处),并且非常高效。

【讨论】:

  • Boost.Asio 是另一个编写良好且易于使用的套接字库。
  • 好建议,如果 OP 已经对 Boost 感到满意,这可能是一个更简单的选择。
  • @Chris 所以基本上我需要为每个客户端维护一个“keep-alive”套接字来推送新数据,并且还有一些方法(辅助套接字/端口)来监听来自客户端的传入连接?
  • 这不是一个“keep-alive”套接字,它是一个套接字。这是您与客户的直接联系。是的,传入队列也恰好是一个套接字。但请放心,即使在最简单的情况下,您仍然至少有两个插槽在使用。
【解决方案2】:

据我了解,我认为您需要保持无限循环运行(至少在程序终止之前),以响应来自您的客户端的连接请求。最好将它们添加到某种数组中。使用事件查看何时将新客户端添加到该数组,并等待其中一个提供数据。然后你对这些数据做你必须做的事情并将其吐回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多