【问题标题】:Question about server socket programming model [closed]关于服务器套接字编程模型的问题[关闭]
【发布时间】:2010-10-27 04:55:15
【问题描述】:

在过去的几个月里,我一直致力于用 C++ 和 Java 实现一些套接字服务器。我用 Java 编写了一个小型服务器,可以处理和处理来自网站上托管的 flash 应用程序的输入,并且我成功地编写了一个服务器,可以处理来自 C++ 中具有多个玩家的 2D 游戏客户端的输入。我在一个项目中使用了 TCP,在另一个项目中使用了 UDP。现在,我确实有一些我在网上找不到的问题,我希望一些专家可以帮助我。 :)

假设我想用 C++ 构建一个服务器来处理来自数千个独立和/或 Web 应用程序的输入,那么我应该如何设计我的服务器?到目前为止,我通常为每个连接的用户创建一个新的和独特的线程,但我怀疑这是要走的路。

另外,如何确定通过网络发送的数据包的布局?数据通常是以二进制还是文本状态通过网络发送的?当您将数据发送到不同的媒体(例如 C++ 服务器到闪存应用程序)时,您如何处理序列化的对象?

最后,除了 boost asio 之外,是否还有任何易于使用且支持可移植性(例如在 windows 机器上开发和在 linux 机器上部署)的常用库。

谢谢。

【问题讨论】:

    标签: c++ sockets


    【解决方案1】:

    关于服务器套接字和序列化(编组)。最重要的问题是不断增长的套接字数量在 select 中处于可读可写状态。我不是关于 FD_SET 的限制。这可以简单地解决。我是关于在处理评估套接字中可用的数据时,未读取套接字中的信令时间和问题数据积累的增长。所以解决方案可能甚至超出了软件边界,需要多处理器模型,当处理器的角色有限时:一个读取和写入,N个处理。在这种情况下,当 select 返回并发送到另一个处理单元时,应该已经读取了所有可用的套接字数据。

    传入数据也是如此。

    关于编组。粗略的二进制格式更可取,因为性能。顺便说一下,在 UNICODE 方面的 XML 也有同样的问题。但是,...同志们,这不仅仅是将长整数或整数值复制到套接字流中。但在这种情况下,即使是 htons,htonl 也可以提供帮助(它以 NW 格式发送/接收,操作系统负责数据转换)。但是在表示头之后发送数据更安全,其中最高/最低有效位的公开格式、字节顺序和 IEEE 数据类型。这行得通,我没有一个案例。

    向大家致以诚挚的问候和巨大的成功。 西蒙·康托尔

    【讨论】:

      【解决方案2】:

      1) 最后,除了 boost asio 之外,是否还有任何易于使用且支持可移植性(例如在 windows 机器上开发和在 linux 机器上部署)的常用库。 p>

      ACE 库是另一种选择。它非常成熟(自 90 年代初就已经存在)并且被广泛部署。在Riverace 网站here 上提供了关于它与Boost ASIO 比较的简短讨论。请记住,ACE 长期以来必须支持大量遗留平台,因此它没有像 Boost ASIO 那样充分利用现代 C++ 功能。

      2) 假设我想用 C++ 构建一个服务器来处理来自数千个独立和/或 Web 应用程序的输入,那么我应该如何设计我的服务器?到目前为止,我通常为每个连接的用户创建一个新的独特线程,但我怀疑这是要走的路。

      有许多常用的方法,包括但不限于:thread-per-connection(您描述的方法)和 线程池(Justin 描述的方法)。每个都有其优点和缺点。许多人都看过权衡取舍。一个好的起点可能是Thread Pool Pattern Wikipedia 页面上的链接。

      Dan Kegel 的“The C10K Problem”网页也有很多关于提高可扩展性的有用说明。

      3) 另外,如何确定通过网络发送的数据包的布局;数据通常是以二进制还是文本状态通过网络发送的?当您将数据发送到不同的媒体(例如 C++ 服务器到闪存应用程序)时,您如何处理序列化对象?

      我同意其他人的观点,即发送二进制数据通常是最有效的。 boost serialization 库可用于将数据编组为二进制形式(以及文本)。成熟的二进制格式包括XDRCDR。例如,CDR 是 CORBA 使用的格式。 ZeroC公司定义了ICE编码,应该比CDR效率高很多。

      有很多二进制格式可供选择。我的建议是至少通过阅读其中一些二进制格式来避免重新发明轮子,这样您就不会遇到这些现有二进制格式旨在解决的相同陷阱。

      也就是说,很多 middleware 已经为您的大部分需求提供了固定解决方案。例如,OpenSpliceOpenDDS 都是 OMG Data Distribution Service 标准的实现。 DDS 侧重于通过publish-subscribe model 等有效分发数据,而不是远程调用函数。我更熟悉 OMG 定义的技术,但我确信还有其他中间件实现可以满足您的需求。

      【讨论】:

        【解决方案3】:

        您仍然需要一个套接字来处理每个客户端,但我们的想法是创建一个 X 套接字池(例如 50 个),然后在您接近(例如 90%)时消耗所有这些套接字,创建另一个 X 套接字池。在某些时候,在客户端连接、发送数据和断开连接后,您的一些套接字将可供使用并且您可以使用它们(此信息的谷歌套接字池)

        数据的布局总是很困难。如果您的所有客户端和服务器都将使用相同的硬件和操作系统,您可以以二进制格式发送数据,但那里有很多行程和陷阱(字节对齐位于列表顶部)。发送格式化文本总是更容易,但在带宽和处理能力方面肯定更昂贵,因为您必须在发送之前将格式从机器更改为文本,当然还要在接收器处再次返回。

        re: 序列化,对不起,我帮不了你,也帮不了库(我太嵌入了,没用过很多)

        【讨论】:

        • 看来你在这里混淆了套接字和线程。
        • 是的,我一开始就混淆了我的条款(现在已修复)
        【解决方案4】:

        虽然之前的答案提供了很好的方向,但只是为了完整性,我想指出线程并不是出色的套接字服务器性能的绝对要求。一些例子是here。可扩展性也有很多方法 - 线程池、预分叉进程、服务器池等。

        【讨论】:

          【解决方案5】:

          就服务器设计而言,我会说你是对的:虽然 ONE-THREAD-PER-SOCKET 是一种简单易行的方法,但它不是可行的方法,因为它的扩展性不如其他服务器设计模式。

          我个人喜欢 COMMUNICATION-THREADS/WORKER-THREADS 方法,其中动态数量的工作线程池处理生产者线程生成的所有工作。

          在此模型中,池中有多个线程等待将由另一组处理网络 I/O 的线程生成的任务。

          我发现了 Richard Stevens 的 UNIX Network Programming 以及关于网络编程方法的此类惊人来源。而且,尽管它的名字,它在 Windows 环境中也将非常有用。

          关于数据包的布局(在我看来,您应该为此发布一个不同的问题,因为这是一个完全不同的问题),在选择 TEXT 与 BINARY 方法时需要权衡取舍。

          TEXT(即 XML)可能更容易解析和记录,并且通常更简单,而 BINARY 协议在处理速度和网络数据包大小方面应该为您提供更好的性能,但您将不得不处理更复杂的问题,例如单词的ENDIANNES之类的。

          希望对你有帮助。

          【讨论】:

            【解决方案6】:

            听起来您有几个问题。我会尽我所能回答我能看到的。

            1.我应该如何处理我的网络服务器中的线程?

            我会好好看看你在你的服务器产生的工作线程上做了什么样的工作。为每个请求生成一个新线程并不是一个好主意……但如果并行请求的数量很少并且每个线程上执行的任务运行速度很快,它可能不会造成任何损失。

            如果您真的想以正确的方式做事,您可以拥有一个可配置/动态的线程池,以便在工作线程空闲时回收它们。这样您就可以设置最大线程池大小。然后,您的服务器将达到池大小...然后发出进一步的请求,直到有工作线程可用。

            2。如何格式化数据包中的数据?

            除非您正在开发一个全新的协议...这不是您真正需要担心的事情。除非您正在处理流媒体(或其他可以接受数据包丢失/损坏的应用程序),否则您可能不会为此应用程序使用 UDP。 TCP/IP 可能是您最好的选择……这将决定您的数据包设计。

            3。我使用哪种格式进行序列化?

            通过网络对数据进行序列化的方式取决于将使用您的服务的应用程序类型。二进制序列化通常更快,并且需要通过网络传输的数据量更少。使用二进制序列化的缺点是一种语言的二进制序列化在另一种语言中可能不起作用。因此,连接到您服务器的客户端很可能必须使用与您使用的语言相同的语言编写。

            XML 序列化是另一种选择。这将需要更长的时间并且需要通过网络传输更多的数据。使用 XML 序列化之类的好处是,您将不受限于可以连接到您的服务器并使用您的服务的客户端类型。

            您必须选择最适合您的需求。

            ...尝试不同的选项并找出最适合您的选项。希望您能找到比我在这里提到的任何东西都更快、更可靠的东西。

            【讨论】:

            • 我非常喜欢你的回答。快速澄清一下:是否有可以兼容多种语言的序列化方案?比如Java Native序列化是否兼容.NET的?
            • 如果您在谈论二进制序列化格式......我不知道。基于文本的序列化(如 XML、JSON 等)是唯一的,因为它们将低级表示留给语言(C# 中的 List 可能最终成为 Java 中的 T[])
            • 今天早上我意识到我忘了提到 COM+ 和 DCOM。这些技术在您的组件之上提供了一个二进制兼容层。您必须使用 COM 兼容类型...但它是跨语言的二进制序列化。
            • 恕我直言,我相信 Protocol Buffers 也适合二进制序列化。
            • 这里是en.wikipedia.org/wiki/Hessian_(web_service_protocol)中的二进制序列化
            猜你喜欢
            • 2010-09-15
            • 1970-01-01
            • 1970-01-01
            • 2018-09-09
            • 1970-01-01
            • 1970-01-01
            • 2014-08-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多