异步服务器套接字多个客户端

Posted

技术标签:

【中文标题】异步服务器套接字多个客户端【英文标题】:Asynchronous server socket multiple clients 【发布时间】:2011-08-14 12:35:55 【问题描述】:

我一直在使用 msdn 上发布的以下代码:

http://msdn.microsoft.com/en-us/library/fx6588te.aspx

我了解服务器应用程序在等待新客户端时没有被阻止。

但是,这个应用程序(甚至套接字)可以处理多个并发请求吗?

如果客户端 A 和 B 同时连接会发生什么?

如果客户端 A 连接并且处理其请求需要 5 秒,如果客户端 B 稍后连接,它是否必须等待客户端 A 完成才能开始处理?

还是会同时处理客户端A和客户端B的请求?

我通过在套接字侦听器代码中的接收/发送数据之间放置 Thread.Sleep(n) 命令对此进行了一些测试。然后我可以向套接字发送多个请求,它们似乎已被处理。然而,套接字总是在 same 线程 id 上处理它们——这让我相信它实际上并没有同时发生。

特别是考虑到微软的描述,这个应用程序在等待新连接时根本不会阻塞 - 这是否意味着它 可以处理并发连接?

【问题讨论】:

实际上,该页面指出服务器应用程序的执行在等待来自客户端的连接时不会暂停,因为所有调用都是使用异步回调完成的,这意味着在等待连接或数据时,您的主线程不会被阻塞。但是是的,它可以在多个线程上同时接收数据,尽管对于单个传入连接只能激活一个“接受”回调(这意味着在接受连接时您必须快速完成工作)。 Hy RemotecUK,您能否发布更新后的代码以接受多个连接。我还使用了 MSDN 示例,需要多个连接来处理。请帮忙。 【参考方案1】:

[2014 年更新]: 自发布此答案以来,该示例似乎已被修改,如 this thread 中所述。 MSDN 示例现在可以正确处理多个传入连接。无论如何,这里描述的一般方法是正确的,也许它可以提供额外的说明。


在进行套接字通信时,基本上所有传入连接都有一个 listener 套接字,每个连接的客户端都有多个 handler 套接字。

监听传入连接

当您开始侦听端口时,您会创建一个带有回调方法的套接字用于传入连接(这是引用您提到的the example)。这是该端口号的唯一侦听器套接字

listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);

这行告诉侦听器在连接新客户端时调用AcceptCallback 方法(新连接回调)。该方法应该可以快速完成工作,因为它会阻止其他传入连接。

创建专用处理程序套接字

这也是为什么AcceptCallback必须立即创建一个专用的“handler”套接字,并使用自己的后台数据回调方法(ReadCallback):

// inside AcceptCallback, we switch to the handler socket for communication
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
    new AsyncCallback(ReadCallback), state); // fired on a background thread

从那一刻起,只要新连接的客户端收到一些数据,就会调用ReadCallback 方法。

另外,在返回之前,AcceptCallback 需要再次调用listener.BeginAccept,以继续监听新的传入连接:

// this is the same server socket we opened previously, which will now 
// continue waiting for other client connections: it doesn't care about
// the actual data transmission between individual clients
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);

MSDN 示例中省略了这部分,表示它只能接收单个连接。

接收数据

一旦你从你的客户端得到一个数据包,ReadCallback 方法就会被调用。所以,在这个数据回调方法中,你需要读取和处理接收到的数据,然后调用同样的BeginReceive方法再次(同样,ReadCallback作为它的数据回调方法)。

[编辑]

MSDN 示例的问题是它只允许连接一个客户端(listener.BeginAccept 只被调用一次)。要允许多个并发连接,您需要使用handler.BeginReceive 创建一个接收套接字,然后调用listener.BeginAccept 开始监听新的客户端。

【讨论】:

感谢您的回复!你今天为我拯救了冠军联赛:)。我在BeginReceive 之前调用了BeginAccept 的新连接,这让我遇到了一个问题。 Hy Groo,您能否发布您更新的 MSDN 示例代码以接受多个连接。我需要它。请帮忙。 @daniel:这实际上接受多个连接的代码。每当建立新连接时都会调用AcceptCallback,并在其中调用listener.BeginAccept 会为该连接返回一个专用 Socket(然后与它自己的ReadCallback 处理程序相关联)。如果您有特定的用例,请发布一个包含详细信息的单独问题。 你好,请查看我的这个问题***.com/questions/25404114/…,并提供帮助。谢谢【参考方案2】:

每个套接字都会有一个与之关联的监听队列。这将有待处理/部分接受的传入连接。挂起连接的最大数量可以在listen() API 中以编程方式定义,在本例中只是“listener.Listen(100)”。在这里设置为 100,套接字“侦听器”可以在侦听队列中有 150 (=2*100/2) 个挂起的连接。

【讨论】:

2 * 100 / 2 = 150?没办法。

以上是关于异步服务器套接字多个客户端的主要内容,如果未能解决你的问题,请参考以下文章

提升异步 tcp 客户端

select+异步

在异步套接字中向特定客户端发送数据

如何让我的异步客户端调用套接字服务器并等待响应

ZeroMQ,异步阻塞套接字

C#异步套接字服务器没有收到来自Java客户端的响应