我正在network programming
上学习MFC
,并在这里引用了比目鱼的指南:http://www.flounder.com/kb192570.htm来搞乱多线程和套接字。但我的工作更简单。
我想要做的是制作一个多线程服务器客户端模型。服务器只是坐着听,而客户端telnet到它。一旦有连接,服务器将创建线程来处理OnAccept()
中的连接。在创建时,线程将PostMessage
及其主线GUI的线程ID。然后GUI使用函数处理该消息,以弹出MessageBox
以显示线程ID。就这么简单。
我的问题是:尽管成功制作了线程,依赖套接字句柄(我已在netstat
上检查过),但线程的通知消息从未发送到GUI。
这是我的代码:
CListenSocket.h
和CConnectSocket.h
在.h中非常相同(源自CSocket
)
......
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;
....
现在,当我创建listen套接字时,我已经将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 :(得分:0)
我找到了解决这个问题的方法,但我仍然不知道为什么我以前的工作没有按照我的预期工作。
我将CListenSocket.h
更改为:
public:
void SetParentDlg(CDialog *pDlg) {parrentDlg = pDlg;}
....
protected:
CDialog *parrentDlg;
所以我要做的不是将CWnd
存储在套接字中,而是将CDialog
存储在GUI中。现在当我创建socket时:
m_Listener.Create(1001);
m_Listener.Listen();
m_Listener.SetParentDlg(this);
通过这样做,我可以将套接字OnAccept()
覆盖到主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);
}
然后在我的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传递给线程......请问有什么想法吗?