【问题标题】:TCP server- connection handlingTCP 服务器 - 连接处理
【发布时间】:2015-02-08 17:52:40
【问题描述】:

我有一个 C# 应用程序,它是一个侦听端口的 TCP 服务器。 GPS 设备连接到此端口。应用程序正在接受 TCP 客户端并为每个客户端创建一个新线程。客户端 ID 保存在哈希表中,当客户端连接时更新。这一切都很好,直到大约 400 个单位。一旦单元数量增加,服务器就无法处理所有连接。连接不断被丢弃,有时会导致服务器 CPU 和内存消耗殆尽并将其关闭。解决方法是打开另一个 TCP 服务器实例,侦听不同的端口,并将一些单元转移到该端口。目前大约有 1800 台设备在 8 个不同的端口上运行。服务器非常不稳定,单位仍然无法保持连接。每天面对太多的问题。还使用远程处理通过远程处理端口发送设置 - 这仅在某些情况下有效。

请为 TCP 套接字/线程/线程池等提供解决方案,该解决方案既可扩展又强大,并且可以在单个端口中使用。

此 TCP 服务器在带有 IIS7 和 SQL server 2008 的 Windows server 2008 R2 Enterprise 中运行。
处理器:Intel Xenon CPU E3-1270 V2 @3.50GHz
内存:32GB 系统:64位操作系统

谢谢 乔纳森

【问题讨论】:

  • 每个客户端一个线程根本无法在 Windows 上扩展。您需要在 .NET 中使用几种异步 API 模型之一进行网络连接。请注意,无论如何,您总会有一个限制。但是使用基本的异步 I/O(BeginXXX() 方法或 NetworkStream 类上的 XXXAsync() 方法)您应该能够轻松处理多达数万个连接,并且如果您使用更高效的 XXXAsync() Socket 类上的方法(与异步流方法不同),您应该能够处理成百上千的方法。
  • 还要注意,以上假设您自己的代码的其余部分写得很好。有很多方法可以破坏网络服务器的可伸缩性。您没有提供足够的信息让任何人知道您的实际问题是什么,但我们可以肯定地说,您当前的实现至少有一个已知的可伸缩性问题。
  • @PeterDuniho 这种套接字连接方案是否也适用于桌面 Windows 操作系统,例如Windows 7 专业版 x64。在桌面操作系统上运行套接字服务器时,数千个连接仍然合理吗?

标签: c# multithreading sockets tcpserver


【解决方案1】:

基本上,不要为每个套接字使用一个线程;使用其中一个异步 API(BeginReceive / ReceiveAsync),或某种套接字轮询(例如Socket.Select,尽管请注意这是以非常尴尬的方式实现的;当我使用它时,我实际上使用 P /Invoke 以获取原始的底层 API)。此刻,我有> 30k 个套接字每个进程 与我们的网络套接字服务器(通过Socket 实现)通信。请注意,出于操作系统的原因,我们确实将其拆分为几个不同的端口 - 主要是由于我们的负载平衡器的限制:

【讨论】:

  • @Mark 我相信你的环境比我工作的要大得多。你有可能降到我的水平并帮助我吗?如何发送我的代码?我在代码的各个地方都需要帮助。
  • @Jonathan 超出“每个套接字的线程不起作用”的规模(这已经适用于您),规模在很大程度上无关紧要 - 问题只是您需要切换到异步 IO跨度>
  • @Mark Gravell - 我已切换到异步 IO……我正在改造我的 TCP 服务器……
  • @MarcGravell 在桌面 Windows 操作系统上运行套接字服务器时,有人能合理地期待这种性能吗?
  • @khargosh 桌面操作系统和服务器操作系统之间的配置差异之一是默认情况下可用于网络之类的句柄/临时端口等的数量,因为(奇怪的是)服务器操作系统预计将用作服务器。您可以重新配置桌面网络堆栈以获得类似的级别,但如果您正在编写服务器,您可能应该使用服务器操作系统
【解决方案2】:

每个连接一个线程并不是一个好主意,特别是当您必须同时处理 100 个客户端时。异步是一些缓冲池/管理的方式。如果您正在寻找从异步套接字开始的东西,请查看 this basic implementation 如果您正在寻找完整的东西,请查看 this(解释:Here) 如果你也愿意check this out。

在 C# 中,您可以使用经典的 BeginXXX/EndXXX 方法。 Microsoft 也有一个High Performance Socket API,可以使用XXXAsync 方法加以利用。几篇解释高性能套接字 API Here 和 Here 的文章

【讨论】:

  • 感谢大家给我正确的方向。感谢 Abdullah 提供代码的具体链接。我正在努力实现它......会让你知道它是怎么回事......
  • 大家好,我已经在我的测试环境中运行了服务器和客户端应用程序。在我能够将其实时化之前,还有很多工作要做。
  • 我无法控制我的实际客户端功能。它与服务器建立连接,然后在接下来的 2 分钟内随时发送数据。此代码基于包含的客户端程序的行为方式。在使用另一个简单的客户端进行调试时,客户端只是连接(尚未发送数据),它在 receiveSendToken.theDataHolder.dataMessageReceived = new Byte[receiveSendToken.lengthOfCurrentIncomingMessage]; 处给出内存不足异常。并且 dataMessageReceived 显示为空。我能做什么?
  • 我已将我的设备作为客户端连接到服务器。我被困在 SocketListener 类的第 117 行。 bool incomingTcpMessageIsReady = messageHandler.HandleMessage(receiveSendEventArgs, receiveSendToken, remainingBytesToProcess);应该发送一个真实的,然后才会开始进一步的处理。我发现在句柄 Message 中,receiveSendToken.lengthOfCurrentIncomingMessage 显示了一个非常大的值,例如 1677777,其中好像连接了定制客户端,它的值仅为 5。所以它继续接收数据,看起来它正在等待 1677777 个字节。请帮忙!
  • @Jonathan 您正在构建数据...对吗?如果您不想在这里发布您的代码....您可以使用我个人资料中的电子邮件地址与我联系
猜你喜欢
  • 1970-01-01
  • 2021-04-20
  • 1970-01-01
  • 2011-11-09
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 2019-11-30
相关资源
最近更新 更多