【问题标题】:Multithreading - Disconnect TCP Connection多线程 - 断开 TCP 连接
【发布时间】:2011-05-20 05:49:43
【问题描述】:

我创建了一个线程来接收阻塞套接字,它一直等到数据包到达。但是,当我尝试断开与主线程的连接时,线程之间会出现竞争条件,从而导致错误。

这里的切换发生在线程之间的第 5 行,而没有真正完成断开调用。

void Disconnect() {
    if(isConnected) {
        if (closesocket(sockClient) != SOCKET_ERROR) {
            isConnected = false;
        }
    }
}

我应该如何避免开关并优雅地让它完成断开呼叫?

【问题讨论】:

    标签: c++ windows multithreading tcp


    【解决方案1】:

    这里有两种可能的解决方案。

    您可以在套接字(非主)线程中隔离所有套接字访问,而不是将套接字与主线程断开连接,而是让该线程向非主线程发出信号,表明需要断开连接(或其他一些操作)。这将要求您的辅助线程等待两个对象 - 套接字和指示需要断开连接的信号器(例如 Win32 Event)。

    另一方面,如果您希望允许主线程断开连接(就像您现在所做的那样),您需要检查所有使用套接字的代码,并使用锁保护使其线程安全,以确保并发访问套接字和相关的状态数据被阻止。 Boost.Thread 有合适的锁,你可以在这里使用,否则你可以将自己的锁实现为 Win32 CriticalSection 之类的包装器。

    第二个是我首选的解决方案——您提出这个问题意味着您无论如何都需要回过头来考虑设计中的线程安全性。即使您采用上面的第一个想法,您仍然可能需要维护状态以避免从主线程发送多个断开信号,并且必须进行锁定保护。此外,如果您希望非主线程处理“断开连接”以外的传入事件,则必须在线程之间管理关联状态。

    我认为从现在开始,阻力最小的路径是在现有代码中添加锁定。确保您的锁定范围尽可能小 - 例如,不要设置您在任何可能阻塞或需要很长时间的套接字调用中持有的锁定。

    【讨论】:

    • 在辅助线程中,我有一个无休止的 while 循环调用 receive() 来检查消息,并且在那个接收调用中有一个阻塞的 recv() 等待消息。当它在套接字上等待时我将如何发出信号?
    • 您可以在WaitForSingleObject(terminateEvent) 上使用循环并始终发布异步接收。正如我所指出的,这是第二种方法对您来说可能不那么痛苦的另一个充分理由。
    • 我在 Disconnect() 的开始和结束时设置了 SetEvent() 和 ResetEvent() 以及一段时间 (WaitForSingleObject(terminateEvent, 0)==WAIT_TIMEOUT) 来检查锁而不是布尔 isConnected .它有效,但我猜你真正的意思。
    猜你喜欢
    • 2013-01-07
    • 2014-01-13
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多