首页 文章

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

提问于
浏览
12

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

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

我知道在应用程序等待新客户端时,服务器应用程序未被阻止 .

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

  • 如果客户A和B同时连接会怎么样?

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

  • 或者客户A和客户B的请求会同时处理吗?

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

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

2 回答

  • 30

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


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

    收听传入的连接

    当您开始侦听端口时,您创建一个套接字,其中包含传入连接的回调方法(这是您提到的引用the example) . 这是该端口号的唯一 listener socket

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

    该行告诉侦听器每当连接新客户端时调用 AcceptCallback 方法( new connection callback ) . 该方法应该快速完成其工作,因为它阻止其他传入连接 .

    创建专用处理程序套接字

    这也是为什么 AcceptCallback 必须立即创建一个具有自己的背景 data callback 方法( ReadCallback )的专用 "handler" socket

    // 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 方法 again (同样, ReadCallback 作为其数据回调方法) .

    [Edit]

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

  • 0

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

相关问题