代码之家  ›  专栏  ›  技术社区  ›  Lars A. Brekken

异步套接字的顺序访问

  •  1
  • Lars A. Brekken  · 技术社区  · 14 年前

    我有一个服务器,它有几个客户机c1…cn,每个客户机都建立了TCP连接。客户不到10000个。

    消息协议是基于请求/响应的,其中服务器向客户机发送请求,然后客户机发送响应。

    服务器有几个线程,T1…TM,每个线程都可以向任何客户机发送请求。我想确保在任何时候只有一个线程可以向特定的客户机发送请求,而其他想要向同一个客户机发送请求的线程必须等待。

    我不想阻止线程同时向不同的客户端发送请求。

    例如,如果T1正在向C3发送请求,则在T1收到响应之前,另一个线程T2不应能够向C3发送任何内容。

    我想在套接字上使用一个简单的锁语句:

    lock (c3Socket)
    {
        // Send request to C3
        // Get response from C3
    }
    

    我使用的是异步套接字,因此我可能不得不使用监视器:

    Monitor.Enter(c3Socket); // Before calling .BeginReceive()
    

    Monitor.Exit(c3Socket); // In .EndReceive
    

    我担心事情会出错,不让监视器离开,因此会阻止对客户机的所有访问。我在想我的心跳线程可以使用monitor.tryenter()超时,并抛出它无法获取监视器的套接字。

    为了能够使用lock()语句,使begin和end调用同步是否有意义?我知道在这种情况下,为了简单起见,我将牺牲并发性,但这可能是值得的。

    我在这里能忽略什么吗?感谢您的任何意见。

    2 回复  |  直到 14 年前
        1
  •  2
  •   Nikolai Fetissov    14 年前

    我的答案是 状态机 每个插槽。国家将是 free busy :

    • 如果插座是 自由的 ,发送方线程将标记它 忙碌的 开始发送到客户机并等待响应。
    • 您可能希望在等待时设置一个超时,以防客户机被某种方式卡住。
    • 如果状态是 忙碌的 -线程休眠,等待信号。
    • 当与客户机相关的超时到期时-关闭套接字,客户机就死了。
    • 成功接收/分析响应时,标记套接字 自由的 再次发出信号/唤醒等待的线程。
    • 只有锁绕套接字状态的查询和操作,而不是实际的网络IO。这意味着每个套接字都有一个锁,加上一些类似于条件变量的等待原语(对不起,不记得.NET中真正提供的是什么)

    希望这有帮助。

        2
  •  2
  •   Steve Strong    14 年前

    您当然不能使用您所描述的锁定方法。因为您的系统主要是异步的,所以您不知道将在什么线程操作上运行。这意味着您可能会在错误的线程上调用exit(并引发SynchronizationLockException),或者某些其他线程可能会调用enter并成功,即使该客户机“正在使用”,只是因为它恰好获得了最初调用enter的同一线程。

    我同意尼古拉的观点,你需要在每个插座旁边保持一些额外的状态,以确定它是否正在使用中。当然,您需要锁定来更新这个共享状态。