2016-05-13 4 views
0

Ich lerne network programming auf MFC und habe hier Flunder Leitfaden hier referenziert: http://www.flounder.com/kb192570.htm mit Multi-Thread-und Socket zu versauen. Aber meine Arbeit ist einfacher.

Was ich versuche, ist ein Multi-Thread-Server-Client-Modell zu machen. Der Server sitzt nur herum und hört zu, während die Clients Telnet dazu machen. Sobald Verbindungen vorhanden sind, erstellt der Server Threads für die Verbindung in OnAccept(). Bei der Erstellung wird der Thread PostMessage mit seiner Thread-ID an die Haupt-GUI übergeben. Die GUI behandelt dann diese Nachricht mit einer Funktion, um eine MessageBox anzuzeigen, um die Thread-ID anzuzeigen. Einfach so.

Mein Problem ist: trotz der Fäden erfolgreich gemacht, und so auf der Socket-Handle die informieren Nachricht von Thread (Ich habe es auf netstat geprüft) noch nie in GUI gesendet.

Hier ist mein Code:
CListenSocket.h und CConnectSocket.h in .h ziemlich gleich sind (abgeleitet von CSocket)Mit CSokcet und CWinThread funktioniert PostMessage vom Thread nicht

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

CClientThread.h (abgeleitet von CWinThread)

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

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

Nun, wenn Ich mache den Listen-Socket, ich habe den CWnd-Zeiger der GUI an ihn übergeben:

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

Dann OnAccept() von CListenSocket der Faden hergestellt ist, aber ich habe nicht vergessen, den CWnd-Zeiger passieren ...

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: Thread-Erzeugung

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

Schließlich I kartiert die THREAD_STARTED mit einer Funktion, nur um dieses einfache Ding zu tun:

Hier

ist die Abbildung:

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

Thema arbeitet, Anschlussbuchse auch funktioniert, aber es gibt keine Nachricht geschrieben wurden. Bitte hilf, wo liege ich falsch. Vielen Dank im Voraus.

+0

Haben Sie 'ON_MESSAGE (THREAD_STARTED, OnThreadStart)' zu Ihrer CServerSideDlg BEGIN/END-Nachrichtentabelle hinzugefügt? – marcinj

+0

Ja, tat ich. und 'THREAD_STARTED' wurde definiert als' WM_USER + 200' –

+0

Sind Sie sicher, dass diese Zeile 'if (threadSocket! = NULL)' korrekt ist? Nach dem Anhängen würde ich annehmen, dass es nicht NULL zurückgibt. – marcinj

Antwort

0

Ich habe eine Arbeit dafür gefunden, aber ich weiß immer noch nicht, warum meine vorherige Arbeit nicht so funktioniert hat, wie ich es erwartet habe.

Ich änderte CListenSocket.h dazu:

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

Also, was ich in Buchse zu tun versuche, die Speicherung nicht CWnd, aber CDialog von der GUI.Nun, wenn ich Buchse erstellen:

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

Auf diese Weise kann ich überschreiben die Buchse des OnAccept() auf eine Funktion im Haupt GUI:

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

Dann auf meinem Dlg, ich habe gerade eine öffentliche Methode machen OnAccept() Thread erstellen und CWnd an den Thread übergeben.

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

Der Rest ist unverändert, und es funktioniert.

Also, warum kann ich nicht CWnd von GUI zu Socket übergeben und dann zu thread? Ich kann es nur einmal von GUI zu Thread übergeben ... Irgendeine Idee, bitte?

Verwandte Themen