【问题标题】:Access a socket that has been passed to thread访问已传递给线程的套接字
【发布时间】:2016-09-03 01:57:29
【问题描述】:

我是 MFC 的 CWinThreadCAsyncSocket 的新手,并尝试通过基于对话框的应用程序自己学习它们。
这是我想要做的: 制作服务器/多客户端模型:当客户端连接到服务器时,服务器将根据客户端数量并传递连接到线程的套接字。我已经推荐这篇文章做传球:https://support.microsoft.com/en-us/kb/175668

我已经成功地在每个连接上创建线程,但是......
我的问题是:我可以从主窗口(GUI)重新访问所有已传递给线程的套接字,以发送(广播)数据到所有客户?

这就是我通过的方式:
在服务器端:

void CMyServerDlg::OnAccept(){
CConnectSoc temp_soc;
m_Listener.Accept(temp_soc);
CSocketThread *pThr = (CSocketThread*)AfxBeginThread(
                                    RUNTIME_CLASS(CSocketThread),
                                    THREAD_PRIORITY_NORMAL,
                                    0,
                                    CREATE_SUSPENDED);
pThr->threadHandleSocket = temp_soc.Detach();
pThr->ResumeThread();
}


注意:m_Listener 是从CAsyncSocket 派生的类的对象,CSocketThread 是从CWinThread 派生的。
在线程标题内,我添加了 2 行:

Public:
CConnectSoc threadSocket;
SOCKET threadHandleSocket;

线程类.cpp内部:

BOOL CSocketThread::InitInstance(){

     threadSocket.Attach(threadHandleSocket);
     return TRUE;
}



有人可以告诉我接下来要做什么将数据发送到这些套接字吗?

【问题讨论】:

  • 使用PostThreadMessage 将消息发布到线程。要将线程中的消息发布到主 GUI,请使用普通的 PostMessage()
  • @cha 感谢您的评论,我做了研究,PostThreadMessage() 需要 m_hthreadID。所以我想我们需要首先从线程中PostMessage() 来获取该ID。并将它们存储在某个数组中,以便主 GUI 可以循环 PostThreadMessage()?这是我需要做的吗?
  • AfxBeginThread 返回一个指向CWinThread 对象的指针,该对象有一个成员函数PostThreadMessage。你只需要存储AfxBeginThread返回的指针。
  • 是的,我想我已经找到了做到这一点的方法。我将在短时间内发布我自己的答案。谢谢你们所有的cmets。

标签: c++ multithreading mfc casyncsocket mfc-networking


【解决方案1】:

经过一番研究,我终于认为我可以回答我自己的问题了,谢谢你的帮助;但请修复我,如果有更好的解决方案或者我的不是一个好习惯。

我的解决方案:
这里的关键词是PostMessage()PostThreadMessage()。我们必须在 GUI 和线程之间进行通信。然而,问题是线程不能调用PostMessage() 这是CWnd 的成员函数向GUI 发送消息(我不知道为什么不)。所以我需要线程类中的一个指针从GUI指向CWnd:

在线程类的头部:

public:
   CWnd *wParrent;

然后在创建线程的阶段,我只需要添加1行:

void CMyServerDlg::OnAccept(){
   CConnectSoc temp_soc;
   m_Listener.Accept(temp_soc);
   CSocketThread *pThr = (CSocketThread*)AfxBeginThread(
                                RUNTIME_CLASS(CSocketThread),
                                THREAD_PRIORITY_NORMAL,
                                0,
                                CREATE_SUSPENDED);
   pThr->wParrent = this;  //<== this line
   pThr->threadHandleSocket = temp_soc.Detach();
   pThr->ResumeThread();
}

通过这样做,我现在可以从线程发布消息以向 GUI 提供我的线程 ID。
在线程.cpp中:

BOOL CSocketThread::InitInstance(){
   threadSocket.Attach(threadHandleSocket);
   wParrent->PostMessage(THREAD_STARTED, 0, (LPARAM)m_nThreadID);
   return TRUE;
}

然后在 GUI:我们处理消息 THREAD_STARTED 并使用一个函数来存储 m_nThreadID 以供将来使用:
Dlg 标头中的某处:

CDWordArray m_threadIDs;

Dlg .cpp

LRESULT CMyServer3Dlg::OnThreadStart(WPARAM, LPARAM lParam){
   DWORD ThreadID = (DWORD)lParam;
   m_threadIDs.Add(ThreadID);
   return 0;
}

向所有客户端发送数据时,通过m_ThreadIDs循环使用PostThreadMessage()

for (int i =0; i<m_threadIDs.GetCount(); ++i){
   PostThreadMessage(m_threadIDs[i],SEND_DATA,(WPARAM)bufferSize,(LPARAM)socketBuffer);
}

使用函数在线程中处理SEND_DATA 消息以进行发送:
在线程 .cpp 中:

void CSocketThread::SendDataFunc(WPARAM wParam, LPARAM lParam){
   ASSERT(threadSocket != NULL);
   if(threadSocket == NULL)
   {
       return;
   }
   else
   {
       char *socketBuffer = (char*)lParam;
       int bufferSize = (int)wParam;
       send(threadSocket, socketBuffer, bufferSize, 0);
   }

这就是我所做的,到目前为止没有问题......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    • 2013-12-25
    • 2018-03-27
    相关资源
    最近更新 更多