【问题标题】:How to handle same socket in different threads?如何在不同的线程中处理相同的套接字?
【发布时间】:2009-10-06 06:32:06
【问题描述】:

我正在尝试在不同的线程中处理套接字,从而导致运行时失败。请参阅以下代码。

void MySocket::Lock()
{
    m_LockCount++;

    if( m_LockCount )
    {
        CSocket::Create( 8080 );
    }
}

void MySocket::Unlock()
{
    m_LockCount--;

    if( !m_LockCount )
    {
        CSocket::Close();
    }
}

我从一个线程调用 Lock(),从另一个线程调用 Unlock()。当它执行 CSocket::Close() 时,它会给出一个异常。

我搜索了这个错误并找到了一些原因。 发生这种情况是因为; CSocket 对象应仅在单个线程的上下文中使用,因为由 CAsyncSocket 对象封装的 SOCKET 句柄存储在每个线程句柄映射中。他们还通过在线程之间共享 SOCKET 句柄来提出解决方案 (http://support.microsoft.com/kb/175668)。但这在我的情况下是不可能的,因为我排除了一些不适用于上述解决方案的通知回调。任何人都可以建议一种机制来在线程之间共享 CSocket 而不会影响通知回调?

【问题讨论】:

  • 顺便说一句,在多线程环境中使用 ++ 和 -- 将不起作用,因为这些操作不能保证是原子的。您可以使用 InterlockedIncrement() 和 InterlockedDecrement() 来实现原子性。与您面临的问题无关,但请记住。

标签: c++ multithreading exception sockets


【解决方案1】:

您可以直接使用套接字并停止使用显然有缺陷的 MFC 实现 ...

【讨论】:

  • 我一般同意,但如果这不是一个选项,请参阅我的回答。
【解决方案2】:

如果如您所说,“CSocket 对象应仅在单个线程的上下文中使用”,那么就没有“在线程之间共享 CSocket 的机制”。

也就是说,其中一个线程需要拥有CSocket,其他线程不能乱搞。

在这种情况下,解决方案是使用线程间消息传递系统。这样,其他线程之一可以向所有者发送一条消息,说:“嘿,伙计,关闭你的套接字!”

如何进行消息传递的细节完全取决于程序的上下文。

【讨论】:

    【解决方案3】:

    我建议您使用一些更高级别(并且错误更少)的套接字 API,例如 Boost.Asio。请注意,无论如何它都不会使套接字成为线程安全的(请参阅there)。您必须使用一些锁定/解锁功能。

    我不确定我是否理解您关于在不使用通知回调的情况下在线程之间共享套接字的问题。在线程 T1 和 T2 之间,假设 T1 管理一个套接字,那么 T2 只有两种方式可以感知到一个套接字事件。要么是 T1 发出的一些通知,要么是 T2 向 T1 提出的问题,无论是定期还是在阻塞呼叫中。

    【讨论】:

    • 谢谢。我可以添加更多细节。共享套接字实际监听连接。所以 T1 将调用 CSocket::Create() 并且 CSocket 将开始监听。当 T2 启动时,它将增加 m_LockCount。现在假设 T1 已停止。它将递减 m_LockCount。之后 T2 停止。 T2 将 m_LockCount 减为 0 并调用 CSocket::Close()。希望你能理解我应该分享的方式。
    • "因为 CAsyncSocket 对象封装的 SOCKET 句柄存储在每个线程的句柄映射中" 据此,如果 T1 退出,套接字的句柄将丢失,因此 T2 应该无法关闭它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    相关资源
    最近更新 更多