异步服务器套接字多个客户端
我一直在使用 msdn 上发布的以下代码:
http://msdn.microsoft.com/en- us/library/fx6588te.aspx
我知道服务器应用程序在等待新客户端时不会被阻止。
但是,这个应用程序(甚至套接字)可以处理多个并发请求吗?
如果客户端 A 和 B 同时连接会发生什么?
如果客户端 A 连接并且处理其请求需要 5 秒,如果客户端 B 一秒后连接,它必须等待客户端 A 完成才能开始处理吗?
或者客户端A和客户端B的请求会同时处理吗?
我通过在套接字侦听器代码中的接收/发送数据之间放置 Thread.Sleep(n) 命令来对此进行了一些测试。然后我可以向套接字发送多个请求,并且它们似乎已得到处理。然而,套接字总是在相同线程ID上处理它们——这让我相信它实际上并不是同时发生的。
特别是考虑到微软的描述,该应用程序在等待新连接时不会阻塞 - 这是否意味着它可以处理并发连接?
I have been working with the following code published on msdn:
http://msdn.microsoft.com/en-us/library/fx6588te.aspx
I understand that the server application is not blocked whilst the application is waiting for new clients.
However can this application (or even sockets) for that matter handle multiple concurrent requests?
What would happen if client A and B connected at the same time?
If client A connects and the handling of its request takes 5 seconds, if client B connects a second later must it wait for client A to finish before its processing can start?
Or will client A and client B's requests be handled concurrently?
I have done some testing with this by putting Thread.Sleep(n) commands in between the receive/send data in the socket listener code. I can then send multiple requests to the socket and they appear to be handled. However the socket always handles them on the same thread id - which makes me believe that it isnt actually happening concurrently.
Especially given the description by microsoft that this app simply doesnt block whilst awaiting for new connections - does that mean it can handle concurrent connections?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
[2014年更新]:自从发布此答案以来,该示例似乎已被修改,如此中所述线程。 MSDN 示例现在可以正确处理多个传入连接。无论如何,这里描述的一般方法是正确的,也许它可以提供额外的说明。
在进行套接字通信时,基本上有一个用于所有传入连接的侦听器套接字,以及用于每个连接的客户端的多个处理程序套接字。
侦听传入连接
当您开始侦听端口时,您将创建一个带有传入连接回调方法的套接字(这是引用您提到的示例)。这是该端口号的唯一侦听器套接字:
这一行告诉侦听器在连接新客户端时调用
AcceptCallback
方法(新连接回调)。该方法应该能够快速完成工作,因为它会阻止其他传入连接。创建专用处理程序套接字
这也是为什么
AcceptCallback
必须立即创建一个专用“处理程序”套接字及其自己的后台数据回调方法(ReadCallback
):从那一刻起,只要新连接的客户端收到一些数据,就会调用
ReadCallback
方法。另外,在返回之前,
AcceptCallback
需要再次调用listener.BeginAccept
,以继续侦听新的传入连接:这部分在MSDN示例中被省略,意味着它只能接收单个连接。
接收数据
一旦您从客户端收到数据包,
ReadCallback
方法就会被调用。因此,在这个数据回调方法中,您需要读取并处理接收到的数据,然后再次调用相同的BeginReceive
方法(再次使用ReadCallback) code> 作为其数据回调方法)。
[编辑]
MSDN 示例的问题在于它仅允许连接单个客户端(
listener.BeginAccept
仅被调用一次)。要允许多个并发连接,您需要使用handler.BeginReceive创建接收套接字,然后调用listener.BeginAccept开始监听新客户端。[Update 2014]: It seems that the example has been modified since this answer was posted, as noted in this thread. The MSDN example now handles multiple incoming connections properly. Anyway, the general approach described here is correct and perhaps it can provide additional clarification.
When doing socket communication, you basically have a single listener socket for all incoming connections, and multiple handler sockets for each connected client.
Listening to incoming connections
When you start listening to a port, you create a socket with a callback method for incoming connections (this is referencing the example you mentioned). That's the one-and-only listener socket for that port number:
This line tells the listener to invoke the
AcceptCallback
method whenever a new client is connected (new connection callback). That method is the one which should do its work quickly, since it blocks other incoming connections.Creating dedicated handler sockets
That is also why
AcceptCallback
must immediately create a dedicated "handler" socket with its own background data callback method (ReadCallback
):From that moment on,
ReadCallback
method is invoked whenever some data is received by your newly connected client.Also, before returning,
AcceptCallback
needs to calllistener.BeginAccept
again, to continue listening to new incoming connections:This part is omitted from the MSDN example, meaning it can only receive a single connection.
Receiving data
As soon as you get a packet of data from your client,
ReadCallback
method will be invoked. So, inside this data callback method, you need to read and process the received data, and then invoke the sameBeginReceive
method again (again, withReadCallback
as its data callback method).[Edit]
The problem with MSDN example is that it allows connection of only a single client (
listener.BeginAccept
is called only once). To allow mulitple concurrent connections, you need to create a receive socket usinghandler.BeginReceive
, and then calllistener.BeginAccept
to start listening to new clients.每个套接字都有一个与其关联的监听队列。这将具有待处理/部分接受的传入连接。挂起连接的最大数量可以在listen() API中以编程方式定义,在本例中它只是“listener.Listen(100)”。此处设置为 100,套接字“侦听器”在侦听队列中可以有 150 (=2*100/2) 个待处理连接。
Every socket will have a listen queue associated with it. This will have the pending/partially accepted incoming connections. The max number number of pending connections can be defined programmatically in listen() API, which is nothing but 'listener.Listen(100)' in this example. Having had this as 100 here, the socket 'listener' can have 150 (=2*100/2) pending connections in the listen queue.