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

本文关键字:客户端 套接字 服务器 异步 | 更新日期: 2023-09-27 17:54:03

我一直在处理msdn上发布的以下代码:

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

我明白当应用程序等待新客户端时,服务器应用程序不会被阻塞。

然而,这个应用程序(甚至套接字)可以处理多个并发请求吗?
  • 如果客户端A和B同时连接会发生什么?

  • 如果客户端A连接并且处理它的请求需要5秒,如果客户端B在一秒后连接,它必须等待客户端A完成才能开始处理吗?

  • 还是客户端A和客户端B的请求会被并发处理?

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

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

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

[Update 2014]:似乎这个例子已经被修改,因为这个答案被张贴,如在这个线程中所指出的。MSDN示例现在可以正确地处理多个传入连接。无论如何,这里描述的一般方法是正确的,也许它可以提供额外的澄清。


在进行套接字通信时,基本上只有一个监听器套接字用于所有传入的连接,而多个处理程序套接字用于每个连接的客户端。

监听传入连接

当您开始侦听端口时,您将为传入连接创建一个带有回调方法的套接字(这引用了您提到的示例)。这是该端口号的惟一的侦听器套接字:

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

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

创建专用处理程序套接字

这也是为什么AcceptCallback必须立即创建一个专用的"处理程序"套接字和它自己的后台数据回调方法(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开始侦听新的客户端。

每个套接字都有一个与之相关联的监听队列。这将包含挂起/部分接受的传入连接。挂起连接的最大数目可以在listen() API中以编程方式定义,在本例中就是'listener.Listen(100)'。将此值设置为100后,套接字'侦听器'可以在侦听队列中拥有150(=2*100/2)个待挂连接。