构建多线程TCP / IP服务器

时间:2010-02-18 15:58:22

标签: delphi tcp delphi-2010

我想构建一个最多可由100个并发客户端使用的TCP / IP服务器,但仍不确定如何开始使用。

至少我需要服务器:

  1. 聆听客户端,并将所有内容存储在数组或列表中。
  2. 对于每个客户端,它需要根据客户端状态接收和发送数据。
  3. 当有人连接或断开连接时,服务器应更新客户端列表。
  4. 更喜欢使用GUI来管理它。
  5. 任何人都可以帮忙如何开始,我看了indy示例,但他们没有帮助,也寻找大多数组件但仍在搜索。

7 个答案:

答案 0 :(得分:8)

您需要使用内置多线程的TidTCPServer。您无需管理线程。一切都是透明的,所以在为一个客户端编写应用程序的方式中,(几乎)就像为许多客户端编写应用程序一样。请参阅OnConnect事件。有一个TidContext参数,里面有一个TThreadList。您可以使用该事件“注册”/将客户端添加到自定义阵列/列表,并OnDisconnect删除客户端。

服务器收到消息时会触发OnExecute事件。使用其参数来读取发送的消息。

此外,您需要使用TidTCPClient 另一个应用程序作为您的客户端。在此应用程序中,您将设置服务器的地址(请参阅主机属性)以及应与服务器的地址匹配的端口。您应该调用Connect(当服务器运行时)并发送您拥有SendCmd方法的字符串。 (如果需要,请参阅IOHandler.WriteLn

还有其他一些事情,但我认为这足以让你开始。你也可以在.Delphi.Winsock论坛的Embarcadero论坛上发帖,其中Indy团队成员正在浮动。或许你可以直接在.Delphi.Non-Technical中询问,那里的人会指导你。

另一种方法是 DataSnap ,这是一个比Indy更面向对象的层(不要与DBX混淆),它提供了你的JSON,REST和其他好东西。请参阅小型评论here

答案 1 :(得分:3)

在Windows平台上,最好避免select大量并发连接(尽管100不是大量连接)。但是,avirtuos是正确的,因为您要避免任何“每个连接的线程”模型。 Windows上最有效的方法是使用重叠的I / O和I / O完成端口。这允许您使用少量线程(可能是2或3个)管理数十万个连接。

我没有任何Delphi经验,所以我不知道与C ++代码交互是多么容易但我有一个免费的C ++ I / O完成端口服务器框架(可从here获得) ,至少,向您展示标准的Win32 I / O完成端口API如何运作。它可能对您有用,您可以在Delphi中执行类似的操作。

答案 2 :(得分:3)

另一个Delphi库选项是synapse,它提供了一个可以轻松扩展的简单框架。贡献文件中提供了IOCPPool演示,可能对您有所帮助。

Synapse更像是一个类的框架,而不是一个组件库。有一个充满活力和活跃的用户社区,随时准备支持任何挑战。我在Delphi 2010中使用这个库没有任何问题(虽然我使用的是SVN的最新开发版本)。

由于它们不是组件,因此在简单的控制台应用程序或Windows服务中使用这些类非常容易。

答案 3 :(得分:2)

Indy是您的最佳选择:1000个客户并不是那么多:我开发了一台服务器,必须为4-5 k客户提供服务,并且它可以作为一种魅力。

  1. 聆听客户端,并将所有内容存储在数组或列表中。 + 3.当有人连接或断开连接时,服务器应更新客户端列表。
  2. - >对于客户端列表,您可以遍历存储所有“活动”线程的TidTCPServer(版本9.0)的TThreadList成员,每个线程与客户端连接“等效”,尽管线程可能比客户端连接更长,但是您可以通过设置适当的连接超时值来解决此问题。如果您需要,您还可以维护自己的客户端列表(例如从TList继承或创建Generics.Collection):您将在onConnect事件之后添加客户端信息(tidPeerThread类公开所有客户端信息:IP ...)

    然后,您将定期循环浏览此列表并检查活动连接(ping命令)并杀死/删除所有僵尸。

    [indy documentation] 对等线程连接尝试的事件处理程序。

    属性OnConnect:TIdServerThreadEvent;

    描述

    OnConnect是TIdServerThreadEvents的事件处理程序。当TIdPeerThread尝试连接到TIdTCPServer时发生OnConnect。

    OnConnect接收AThread作为参数,表示请求连接的TIdPeerThread线程。

    将一个TIdServerThreadEvent事件处理程序过程分配给OnConnect。 [/ indy documentation]

    1. 对于每个客户端,它需要根据客户端状态接收和发送数据: - >查看聊天客户端和服务器演示源代码以获取详细示例。

    2. 更喜欢使用GUI作为服务进行管理:您可以开发一个服务应用程序,它可以记录数据库中的所有活动,第二个应用程序将访问该数据库并显示所有可用的统计信息(客户编号) ...)。

    3. 以下是Indy 9.0的链接(来源和文档): http://www.indyproject.org/downloads/Indy_9_00_14_src.zip http://www.indyproject.org/downloads/Indy-9-0-Help-WinHelp.zip

      这是一本Indy书,虽然我认为在阅读文档之后你不会需要它:Indy in depth:http://www.atozed.com/Indy/Book/index.EN.aspx

      在这里寻找一个好的教程: http://www.devarticles.com/c/a/Delphi-Kylix/Creating-Chat-Application-with-Borland-DelphiIndy-The-Client/

      祝你好运

答案 4 :(得分:1)

100个插座并不是那么多。你可能会遇到使用像epoll()之类的麻烦,但是对于这种情况,我只需要设置一个包含所有套接字的FD_SET,在整个集合上设置select(),然后检查每个,然后处理它们。序列。如果我不得不做一些可能耗费时间的事情,我会为消息处理程序使用一个线程池。

答案 5 :(得分:0)

我最近遇到了这个问题。以下是使用EPOLL管理数百个多播套接字的C ++示例的链接。你的是TCP / IP,但这只是一个简单的改变。

您选择哪种方法,对于100多个同步套接字/客户端,如果您的平台支持,您将需要使用依赖于poll,select或者epoll的线程模型。

http://anthonyvirtuoso.com/public/dokuwiki/doku.php/projects:multiplexreceiverepoll

@jfawcett - 在超过~50个FD上选择具有相当大的CPU命中率,具体取决于您实际执行选择的频率。在我上面的评论中,示例类最初使用select但在看到CPU成本(valgrind w / callgrind)后,我切换到了epoll。但肯定选择是一个有效的选择。

答案 6 :(得分:0)

对于像您这样的情况(以及更多)有用的一些优秀的组件集是kbmMWRemObjects。还有其他一些好的设置,我想,你可以搜索档案或在Embarcaderos的Delphi thirdpartytools新闻组中提问。您可以在此处搜索档案: http://codenewsfast.com/