代码之家  ›  专栏  ›  技术社区  ›  William Brendel

在C/C++中实现跨平台、多线程服务器的最佳方法是什么?

  •  10
  • William Brendel  · 技术社区  · 17 年前

    与我一起工作的开发团队的一部分面临着编写与我们的产品集成的服务器的挑战。我们有一些提供C SDK的低级传感器设备,我们希望通过网络共享它们,供收集数据的人使用。听起来很简单,对吧?有人将传感器设备连接到大楼一部分的机器上,并运行我们的服务器,从而与网络的其余部分共享设备。然后,客户端将通过我们的应用程序连接到该服务器,并从该设备收集传感器读数。

    我创建了一个简单的、与语言无关的网络协议,以及一个Java参考实现。问题是创建的实现将与我们的设备一起工作,这些设备只提供用C编写的SDK。我们考虑执行以下操作:

    1. 创建轮询线程,收集并存储每个连接设备的最新读数。
    2. 使用多线程服务器将每个传入连接剥离到工作线程。
    3. 当工作线程收到传感器读取请求时,轮询线程收集的最新值将发送回客户端。

    • 在Windows XP/Vista、Linux和OS X计算机上运行
    • 用C或C++编写,与我们拥有的C SDK进行交互
    • 接受可变数量的同时连接(工作线程)
    • 必须使用线程,而不是分叉(不想处理另一层IPC)

    有人能推荐一个库,最好是一些示例代码来开始使用吗?

    11 回复  |  直到 17 年前
        1
  •  13
  •   Ferruccio    17 年前

    我用过 Boost.Thread & Boost.Asio 在Windows&上构建多线程服务器;Linux系统。这些教程使入门变得容易。

        2
  •  9
  •   Community Mohan Dere    9 年前

    编写这样一个服务器的最好方法不是编写一个,而是重新构建您的系统以使其不必要,和/或重用已经存在的组件。因为:

    有人会连接一个传感器设备 到他们的机器的一部分 构建并运行我们的服务器,因此 网络。

    所以,换一种方式来做。在具有传感器硬件的机器上安装一个简单的客户端,然后一直或定期运行它,并将结果推送(post)到中央服务器。中央服务器甚至可以是标准的web服务器。或者它可能是一个数据库。(请注意,这两个都已经编写好了-无需重新发明轮子;-)

    然后,应用程序的工作方式与您现在想到的相同,但是它从数据库而不是传感器收集数据。然而,在带有传感器的机器上运行的部分已经从多线程定制服务器的噩梦缩小到了一个很好的单线程命令行客户机,它只会 爱交际的 连接,并且可以从cron(或windows上的等效程序)运行。

    即使您需要实时数据采集(从您的描述来看,您似乎不需要),传感器采集器还是最好是客户端而不是服务器。让它打开一个到中央收集器(或一组收集器)的长寿命连接,并等待提供其数据的指示。

    this answer 以及评论

        3
  •  7
  •   ConcernedOfTunbridgeWells    17 年前

    Douglas Schmidt's ACE (Adaptive Communications Environment) 是一个 mature, highly portable 用于构建高性能多线程服务器的开源框架。它主要针对电信应用,但已被广泛使用 variety of projects . 它还带有一个 object request broker TAO (如果你喜欢 CORBA

    该框架的一个著名之处是它支持许多线程模型(线程池、每个请求的线程、异步+线程等),所以您可以以最适合您的应用程序的方式使用它的线程管理。这实际上是系统最有趣的特性——服务器框架功能是现成的。我在这里看到的大多数其他库仍然需要您自己实现大部分功能。

    有相当多的问题 electronic documentation 而且 several books

    哦,顺便说一句,它是 free ecosystem of consultants here.

        4
  •  4
  •   Reunanen    17 年前

    这并不是对您的问题的回答,但因为听起来您实际上更熟悉Java而不是C/C++,为什么不继续您的参考实现,并使用 Java Native Interface . (我从未真正使用过它,但我认为它对于这种情况非常有用。)

    或者,您可以轻松编写一个使用SDK的简单C程序,然后将数据发送到Java程序,例如使用基于套接字的流。通过这种方式,您可以再次处理Java中更困难的内容。

        5
  •  4
  •   Mark Beckwith    17 年前

    我会用QT。它具有跨平台线程支持。良好的文件:

    QT Threading Documentation

    他们的信号/插槽消息传递机制也在线程之间无缝工作。

        6
  •  3
  •   Community Mohan Dere    9 年前

    我还想推荐 The Spread Toolkit ,它(根据该项目的网站)是“一个开源工具包,提供高性能的消息传递服务,能够跨局域网和广域网抵御故障”。我已经在听上去与你非常相似的情况下使用过几次了。本质上,它为您提供了 frankodwyer suggests

    Spread守护进程(即服务器)不是多线程的,但它非常快,可以扩展到至少数百或数千个客户端。此外,该协议满足可靠的IP多播,这(在多客户端环境中)可能会给您(性能方面)相对于仅使用点对点TCP或UDP连接实现的任何东西的明确优势。(但是:不要自己尝试实现可靠的IP多播…显然,Spread项目已经产生了许多博士/硕士论文作为副产品-或者是工具包作为副产品,而主要重点始终是学术研究?我真的不知道…)。

    因为Spread有C和Java客户端API(加上Python),所以它听起来非常适合您的问题。它们有两种许可模式;第一种选择接近BSD。当然,它是跨平台的(关于客户端和服务器)。

        7
  •  2
  •   tonymontana    16 年前

    我用 libevent

    libevent API提供了一种机制,用于在文件描述符上发生特定事件或达到超时后执行回调函数。目前,libevent支持/dev/poll、kqueue、事件端口、select、poll和epoll。

        8
  •  1
  •   oz10    17 年前

    我同意frankodwyer的观点,将协议从拉模型转换为推模型。

    或者,您可以使用广播UDP而不是多播。

        9
  •  0
  •   Filip Ekberg    17 年前

    使用跨平台API或创建您自己的API,并在每个体系结构上进行更改。

    还修订了这一点: http://www.goingware.com/tips/getting-started/

        10
  •  0
  •   Christoph    17 年前

    如果您想使用C(而不是C++),则 NSPR library 可能会提供你所需要的。。。

        11
  •  -2
  •   dicroce    17 年前

    基本上,这个想法是:

    服务器负责接收特定端口上的传入连接,并创建线程(或进程)来处理这些连接。

    当您试图构建一个通用服务器时,您会意识到如果不对协议进行假设,您就无法真正读取或写入任何数据。。。所以,诀窍是使用原型模式。

    在应用程序启动时,server类的用户必须调用如下内容:

    “Server.AttachConnectionPrototype(&MyConnectionObject);”