我一直在使用msdn上发布的以下代码:
http://msdn.microsoft.com/en-us/library/fx6588te.aspx
据我所知,在应用程序等待新客户端时,服务器应用程序未被阻止。
但是这个应用程序(甚至套接字)可以处理多个并发请求吗?
如果客户A和B同时连接会怎么样?
如果客户端A连接并且其请求的处理需要5秒钟,如果客户端B稍后连接,则必须等待客户端A完成才能开始处理吗?
或者客户A和客户B的请求会同时处理吗?
我已经通过在套接字侦听器代码中的接收/发送数据之间放置Thread.Sleep(n)命令来完成一些测试。然后,我可以向套接字发送多个请求,它们似乎已被处理。但是套接字总是在相同的线程id上处理它们 - 这让我相信它实际上并不是同时发生的。
特别是微软的描述,这个应用程序在等待新连接时根本没有阻止 - 这是否意味着可以处理并发连接?
答案 0 :(得分:30)
[2014年更新]:如this thread所述,自从发布此答案后,该示例似乎已被修改。 MSDN示例现在可以正确处理多个传入连接。无论如何,这里描述的一般方法是正确的,也许它可以提供额外的澄清。
进行套接字通信时,基本上所有传入连接都有一个侦听器套接字,每个连接的客户端都有多个处理程序套接字。
当您开始侦听端口时,您创建了一个带有回传方法的套接字(这是引用您提到的the example)。这是该端口号的唯一侦听器套接字:
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
开始侦听新客户端。
答案 1 :(得分:0)
每个套接字都有一个与之关联的侦听队列。这将具有待处理/部分接受的传入连接。可以在listen()API中以编程方式定义挂起连接的最大数量,这在此示例中只是“listener.Listen(100)”。在这里将此值设为100时,套接字“侦听器”在侦听队列中可以有150(= 2 * 100/2)个挂起连接。