2016-05-13 55 views
0

我正在學習network programmingMFC並引用了比目魚的指南在這裏:http://www.flounder.com/kb192570.htm攪亂多線程和套接字。但我的工作更簡單。

我想要做的是製作一個多線程服務器客戶端模型。服務器只是坐在一邊聽,而客戶端則通過遠程登錄。一旦有連接,服務器將通過線程處理OnAccept()中的連接。在創建時,線程將PostMessage與其線程ID到主GUI。 GUI然後用一個函數處理該消息以彈出一個MessageBox來顯示線程ID。就這麼簡單。

我的問題是:儘管成功地線程,等等套接字句柄(我已經檢查它netstat)從線程通知消息從未被髮送到GUI。

這裏是我的代碼:
CListenSocket.hCConnectSocket.h相當的.H(從CSocket派生)使用CSokcet和CWinThread,從線程PostMessage不起作用

...... 
public: 
//Handle CWnd pointer from main GUI 
    void SetParrent(CWnd * w) { windowsParrent = w; } 
    CWnd * GetParrent() { return windowsParrent; } 
protected: 
    CWnd *windowsParrent; 
....... 
}; 

CClientThread.h(從CWinThread派生)

.... 
public: 
    void SetParrent(CWnd * w) { windowsParrent = w; } 
    CWnd * GetParrent() { return windowsParrent; } 

    SOCKET handleThreadSocket; 
    CConnectedSocket threadSocket; 
protected: 
    CWnd *windowsParrent; 
.... 

同現我使偵聽套接字,我已經通過GUI的CWnd指針:

CListenSocket m_Listener; 
.... 
m_Listener.SetParrent(this); 
m_Listener.Create(1001);  
m_Listener.Listen(); 

然後OnAccept()CListenSocket的線由,但我沒有忘記通過CWnd的指針...

void CListenSocket::OnAccept(int nErrorCode) 
{ 
    if(nErrorCode != 0) 
    { 
     CSocket temp_soc; 
     CClientThread *pThr = (CClientThread*)AfxBeginThread(
              RUNTIME_CLASS(CClientThread), 
              THREAD_PRIORITY_NORMAL, 
              0, 
              CREATE_SUSPENDED); 

     pThr->SetParrent(windowsParrent);   
     pThr->handleThreadSocket = temp_soc.Detach(); 
     pThr->ResumeThread(); 
    }  
    CSocket::OnAccept(nErrorCode); 
} 

CThreadClient.cpp:線程創建

BOOL CClientThread::InitInstance() 
{ 
    threadSocket.Attach(handleThreadSocket); 
    if (threadSocket == NULL) 
    { 
    return FALSE; 
    }  
    if (windowsParrent == NULL) 
    { 
     return FALSE; 
    } 
    windowsParrent->PostMessage(THREAD_STARTED,0,(LPARAM)m_nThreadID); 
    return TRUE; 
} 

最後,我用一個函數映射THREAD_STARTED只是爲了做這件簡單的事情:

LRESULT CServerSideDlg::OnThreadStart(WPARAM, LPARAM lparam) 
{ 
    UpdateData(TRUE); 
    DWORD ThreadID = (DWORD)lparam; 
    CString echo; 
    echo.Format("%d",ThreadID);  
    UpdateData(FALSE); 
    AfxMessageBox("Thread stated: "+echo); 
    return 0; 
} 

這裏是映射:

BEGIN_MESSAGE_MAP(CServerSideDlg, CDialog) 
... 
//}}AFX_MSG_MAP 
ON_MESSAGE (THREAD_STARTED, OnThreadStart) 
END_MESSAGE_MAP() 

主題的作品,連接插座也可以,但是沒有消息已經發布。請幫忙,我在哪裏錯了。先謝謝你。

+0

您是否已將'ON_MESSAGE(THREAD_STARTED,OnThreadStart)'添加到您的CServerSideDlg BEGIN/END消息映射中? – marcinj

+0

是的,我做過。 'THREAD_STARTED'被定義爲'WM_USER + 200' –

+0

你確定這行'if(threadSocket!= NULL)'是正確的嗎?附加後,我會假設它會返回非NULL。 – marcinj

回答

0

我想出了一個解決方案,但我仍然不知道爲什麼我以前的工作沒有按照我的預期工作。

我改變CListenSocket.h這樣:

public: 
void SetParentDlg(CDialog *pDlg) {parrentDlg = pDlg;} 
.... 
protected: 
CDialog *parrentDlg; 

那麼什麼,我試圖做的是沒有存儲從GUI插座CWnd,但CDialog。現在,當我創建套接字:

m_Listener.Create(1001);  
m_Listener.Listen(); 
m_Listener.SetParentDlg(this); 

通過這樣做,我可以覆蓋在主界面插座的OnAccept()一個函數:

void CListenSocket::OnAccept(int nErrorCode) 
{ 
if(nErrorCode == 0) 
{ 
    ((CServerSideDlg*)parrentDlg)->OnAccept(); //Here I use the function OnAccept() from GUI to handle accepted connections. 
} 
CSocket::OnAccept(nErrorCode); 
} 

然後在我的DLG,我只是做一個公共方法OnAccept()創建線程並將CWnd傳遞給線程。

void CServerSideDlg::OnAccept() 
{ 

    CSocket temp_soc; 
    if (m_Listener.Accept(temp_soc)) 
    { 
    CClientThread *pThr = (CClientThread*)AfxBeginThread(
             RUNTIME_CLASS(CClientThread), 
             THREAD_PRIORITY_NORMAL, 
             0, 
             CREATE_SUSPENDED); 

    pThr->SetParrent(this);   //pass CWnd to thread 
    pThr->handleThreadSocket = temp_soc.Detach(); 
    pThr->ResumeThread(); 
    } 
} 

其餘沒有變化,它的工作原理。

那麼,爲什麼我不能通過CWnd從GUI到套接字然後線程?我只能通過它一次從GUI到線程...任何想法,請嗎?