高并发TCP客户端的设计

3
我有一个.NET TCP客户端,向一个(.NET async) TCP服务器发送大量消息。
由于TIME_WAIT,我需要不断地向服务器发送消息,但是我在客户端上用光了所有可用的端口。如何让程序持续、可靠地发送消息而不使用所有可用端口呢?是否有一种方法可以重复使用同一个套接字?我查看了Disconnect()和REUSEADDRESS套接字标志,但找不到任何好的使用示例。事实上,大多数来源都建议不要使用Disconnect,因为它只是为低级使用(例如,它只回收套接字句柄)。我想可能需要切换到UDP,或者使用C++和IOCP?
6个回答

5
如果你的服务器和客户端了解数据格式,可以保持套接字的打开状态。关闭套接字是为了让服务器“看到”客户端已经“完成”。如果有某种协议,则服务器可以“知道”何时完成接收数据块。你可以寻找某种结束消息标记,可以传递消息长度,并根据大小读取其余部分等不同方法来实现。但是,没有理由不断地打开和关闭与服务器的连接-这才是导致问题的原因。

1
TCP协议在网络中尽力避免拥塞。所有新的TCP连接都开始于“慢启动”状态,在此状态下它们只发送一个数据包并等待对端的确认。如果收到了ACK,TCP将发送两个数据包,之后是四个、八个,直到达到其最大窗口大小。
如果你需要以高数据速率生成消息,确实需要避免打开和关闭TCP连接。每次打开新连接时,你都会回到慢启动状态。如果你可以保持套接字开启,TCP连接将能够跳过慢启动状态,并能够以更高的速率发送数据。
为了做到这一点,你需要让服务器在同一个连接上处理多条信息(也就是找到一种划分每条消息的方法)。如果你的服务器支持任何形式的HTTP编码,那么这种方法可以使用。一定要检查与“持久”连接或HTTP 1.1相关的任何参数或配置,因为这是HTTP通过单个TCP连接发送多个请求的方式。
你提到的一种选择是UDP。如果你以相当高的速率生成消息,由于队列在某个地方已满,很可能会丢失其中一些消息。如果你发送的消息需要可靠性,UDP可能不是好的选择。

1

您的客户端是否可以保持相同的套接字打开并循环发送消息?

open socket connection

while(running)
    send messages over socket

close socket connection

0

当以那种方式编码时,它不起作用。

服务器只接收第一条消息。

当我打开和关闭套接字时,服务器可以工作,但我用完了客户端端口。

我猜这是我的服务器设计导致我必须像那样编写客户端的原因。

那么如何使用.NET编写异步服务器呢?我已经按照MSDN示例和许多在线示例进行了操作。


0

你的项目是否会受益于消息队列服务?这样,你的客户端可以向服务器传递尽可能多的消息,而服务器只需在能够并且尽快地处理这些消息时从队列中拉取它们。如果你的客户端发送的消息超过了它的处理能力,它们将简单地进入队列等待处理。

一些快速的谷歌搜索结果显示了这个 使用C#构建消息队列服务的MSDN文档


0
编写TCP服务器(无论使用哪种语言)的基本思想是打开一个端口以侦听连接,然后创建新线程或进程来处理新的连接请求。
open a server socket // this uses the port the clients know about

while(running)
    client_socket = server_socket.listen
    fork(new handler_object(client_socket))

这里有一个在C#中的好例子


这个不会很糟糕吗?假设你有1000个连接。你是在建议应该有1000个线程吗? - Arafangion
如果您预计有许多并发连接,则可以考虑使用线程池。这用于为应用程序设置同时活动的线程数上限,并帮助管理它们的使用。 - @Arafangion - Bill the Lizard
仍然看起来很高 - 与select()或其他轮询相比是不必要的开销。 - Arafangion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接