Trung Nguyen
Trung Nguyen

Reputation: 177

Access a socket that has been passed to thread

I am new to MFC's CWinThread and CAsyncSocket, and trying to learn them myself with dialog based application.
Here is what I want to do: make a server/multi-client model: when the number clients connect to server, the server will make threads according to the number of clients and passes the socket connecting to the thread. I have refereed this article to do the passing: https://support.microsoft.com/en-us/kb/175668 .

I have successfully make thread on every connection, but...
My question is: Can I from the main windows(GUI) re-access all sockets that have been passed to threads to send(broadcast) data to all the clients?

This is how I do the passing:
On server side:

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();
}


Note: m_Listener is the object of the class that derived from CAsyncSocket and CSocketThread is derived from CWinThread.
Inside the thread header, I added 2 lines:

Public:
CConnectSoc threadSocket;
SOCKET threadHandleSocket;

Inside the thread class .cpp:

BOOL CSocketThread::InitInstance(){

     threadSocket.Attach(threadHandleSocket);
     return TRUE;
}



Can someone tell me what to do next to send data to those socket?

Upvotes: 0

Views: 528

Answers (1)

Trung Nguyen
Trung Nguyen

Reputation: 177

After some research, I finally think I can answer my own question, thanks for your help; but please fix me, if there is a better solution or mine is not a good practice.

MY SOLUTION:
The key word here is PostMessage() and PostThreadMessage(). We must make the communication between the GUI and the Threads. However, the problem is the thread cannot call PostMessage() which is a member function of CWnd to send message to the GUI (I have no idea why not). So I need a pointer in the thread class to point to the CWnd from the GUI:

In header of the thread class:

public:
   CWnd *wParrent;

Then at the stage of creating thread, I just have to add 1 line:

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();
}

By doing this, I can now post message from the thread to give the GUI my thread's ID.
In the thread .cpp:

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

Then at GUI: we handle message THREAD_STARTED with a function to store m_nThreadID for future use:
Somewhere in Dlg header:

CDWordArray m_threadIDs;

Dlg .cpp

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

When sending data to all clients, use PostThreadMessage() in a loop through m_ThreadIDs:

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

Handle SEND_DATA message in the thread with a function to do the sending:
In thread .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);
   }

That's what I have done, and no problem so far....

Upvotes: 1

Related Questions