可执行环境是一个CDialog程序
在多线程里创建CSocket对象,并连接到某一个服务器。
当调用OnButtonDelete函数时,到m_pSocket->Close();就出错???
具体是
BOOL CAsyncSocket::AsyncSelect(long lEvent)
{
ASSERT(m_hSocket != INVALID_SOCKET); _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
ASSERT(pState->m_hSocketWindow != NULL);//出错 return WSAAsyncSelect(m_hSocket, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, lEvent) != SOCKET_ERROR;
}
程序代码如下:
其中CSocketTest类是派生自CSocket;只是在close()里设置TestMutipleSocketDlg类的m_bConnect=FALSE;其他都不做
头文件为:
// TestMutipleSocketDlg.h : header file
class CTestMutipleSocketDlg : public CDialog
{
public:
CMutex m_Mutex;
CSocketTest *m_pSocket;
public:
int m_iPort;
BOOL m_bEndThread;
BOOL m_bConnect;
BOOL StartSocket();
CTestMutipleSocketDlg(CWnd* pParent = NULL); // standard protected:
HICON m_hIcon; // Generated message map functions
//{{AFX_MSG(CTestMutipleSocketDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnButtonConnect();
afx_msg void OnButtonClose();
afx_msg void OnButtonDelete();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
DWORD WINAPI SocketThread(LPVOID pParam);实现文件为:
// TestMutipleSocketDlg.cpp : implementation file
#include "stdafx.h"
#include "TestMutipleSocket.h"
#include "TestMutipleSocketDlg.h"
#include "SocketTest.h"// CTestMutipleSocketDlg dialog
CTestMutipleSocketDlg::CTestMutipleSocketDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestMutipleSocketDlg::IDD, pParent)
{
m_iPort=8776;
m_bEndThread=FALSE;
m_pSocket=NULL;
m_bConnect=FALSE;
//{{AFX_DATA_INIT(CTestMutipleSocketDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CTestMutipleSocketDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTestMutipleSocketDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}BEGIN_MESSAGE_MAP(CTestMutipleSocketDlg, CDialog)
//{{AFX_MSG_MAP(CTestMutipleSocketDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_CONNECT, OnButtonConnect)
ON_BN_CLICKED(IDC_BUTTON_CLOSE, OnButtonClose)
ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CTestMutipleSocketDlg message handlersBOOL CTestMutipleSocketDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
return TRUE; // return TRUE unless you set the focus to a control
}void CTestMutipleSocketDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CTestMutipleSocketDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTestMutipleSocketDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
DWORD WINAPI SocketThread(LPVOID pParam)
{
CTestMutipleSocketDlg *pSocketDlg=(CTestMutipleSocketDlg*)pParam;
while(pSocketDlg->m_bEndThread==FALSE)
{
//if(pSocketDlg->m_bConnect==FALSE)
{
CSingleLock slock(&pSocketDlg->m_Mutex);
slock.Lock();
pSocketDlg->StartSocket();
slock.Unlock();
Sleep(2000);
}
}
return 0;
}void CTestMutipleSocketDlg::OnButtonConnect()
{
// TODO: Add your control notification handler code here
HANDLE hThrds;
// StartSocket();
hThrds=CreateThread(NULL,0,SocketThread,(LPVOID)(this),0,NULL);
}BOOL CTestMutipleSocketDlg::StartSocket()
{
if(m_pSocket!=NULL)
{
m_pSocket->ShutDown();
//
m_pSocket->Close();//
delete m_pSocket;
m_pSocket=NULL;
}
Sleep(3000);
m_pSocket=new CSocketTest(this);
if(!m_pSocket->Create())
{
this->SetWindowText("socket创建失败");
delete m_pSocket;
m_pSocket=NULL;
return FALSE;
}
if(!m_pSocket->Connect("127.0.0.1",m_iPort))
{
TRACE("Connect Server Error");
this->SetWindowText("服务器断开");
delete m_pSocket;
m_pSocket=NULL;
return FALSE;
}
m_bConnect=TRUE;
return TRUE;
}void CTestMutipleSocketDlg::OnButtonClose()
{
// TODO: Add your control notification handler code here
m_pSocket->Close();
}void CTestMutipleSocketDlg::OnButtonDelete()
{
// TODO: Add your control notification handler code here
CSingleLock slock(&m_Mutex);
slock.Lock(); if(m_pSocket!=NULL)
{
m_pSocket->ShutDown();
m_pSocket->Close();
delete m_pSocket;
m_pSocket=NULL;
}
slock.Unlock();}
在多线程里创建CSocket对象,并连接到某一个服务器。
当调用OnButtonDelete函数时,到m_pSocket->Close();就出错???
具体是
BOOL CAsyncSocket::AsyncSelect(long lEvent)
{
ASSERT(m_hSocket != INVALID_SOCKET); _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
ASSERT(pState->m_hSocketWindow != NULL);//出错 return WSAAsyncSelect(m_hSocket, pState->m_hSocketWindow,
WM_SOCKET_NOTIFY, lEvent) != SOCKET_ERROR;
}
程序代码如下:
其中CSocketTest类是派生自CSocket;只是在close()里设置TestMutipleSocketDlg类的m_bConnect=FALSE;其他都不做
头文件为:
// TestMutipleSocketDlg.h : header file
class CTestMutipleSocketDlg : public CDialog
{
public:
CMutex m_Mutex;
CSocketTest *m_pSocket;
public:
int m_iPort;
BOOL m_bEndThread;
BOOL m_bConnect;
BOOL StartSocket();
CTestMutipleSocketDlg(CWnd* pParent = NULL); // standard protected:
HICON m_hIcon; // Generated message map functions
//{{AFX_MSG(CTestMutipleSocketDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnButtonConnect();
afx_msg void OnButtonClose();
afx_msg void OnButtonDelete();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
DWORD WINAPI SocketThread(LPVOID pParam);实现文件为:
// TestMutipleSocketDlg.cpp : implementation file
#include "stdafx.h"
#include "TestMutipleSocket.h"
#include "TestMutipleSocketDlg.h"
#include "SocketTest.h"// CTestMutipleSocketDlg dialog
CTestMutipleSocketDlg::CTestMutipleSocketDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestMutipleSocketDlg::IDD, pParent)
{
m_iPort=8776;
m_bEndThread=FALSE;
m_pSocket=NULL;
m_bConnect=FALSE;
//{{AFX_DATA_INIT(CTestMutipleSocketDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CTestMutipleSocketDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTestMutipleSocketDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}BEGIN_MESSAGE_MAP(CTestMutipleSocketDlg, CDialog)
//{{AFX_MSG_MAP(CTestMutipleSocketDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_CONNECT, OnButtonConnect)
ON_BN_CLICKED(IDC_BUTTON_CLOSE, OnButtonClose)
ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CTestMutipleSocketDlg message handlersBOOL CTestMutipleSocketDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
return TRUE; // return TRUE unless you set the focus to a control
}void CTestMutipleSocketDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CTestMutipleSocketDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTestMutipleSocketDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
DWORD WINAPI SocketThread(LPVOID pParam)
{
CTestMutipleSocketDlg *pSocketDlg=(CTestMutipleSocketDlg*)pParam;
while(pSocketDlg->m_bEndThread==FALSE)
{
//if(pSocketDlg->m_bConnect==FALSE)
{
CSingleLock slock(&pSocketDlg->m_Mutex);
slock.Lock();
pSocketDlg->StartSocket();
slock.Unlock();
Sleep(2000);
}
}
return 0;
}void CTestMutipleSocketDlg::OnButtonConnect()
{
// TODO: Add your control notification handler code here
HANDLE hThrds;
// StartSocket();
hThrds=CreateThread(NULL,0,SocketThread,(LPVOID)(this),0,NULL);
}BOOL CTestMutipleSocketDlg::StartSocket()
{
if(m_pSocket!=NULL)
{
m_pSocket->ShutDown();
//
m_pSocket->Close();//
delete m_pSocket;
m_pSocket=NULL;
}
Sleep(3000);
m_pSocket=new CSocketTest(this);
if(!m_pSocket->Create())
{
this->SetWindowText("socket创建失败");
delete m_pSocket;
m_pSocket=NULL;
return FALSE;
}
if(!m_pSocket->Connect("127.0.0.1",m_iPort))
{
TRACE("Connect Server Error");
this->SetWindowText("服务器断开");
delete m_pSocket;
m_pSocket=NULL;
return FALSE;
}
m_bConnect=TRUE;
return TRUE;
}void CTestMutipleSocketDlg::OnButtonClose()
{
// TODO: Add your control notification handler code here
m_pSocket->Close();
}void CTestMutipleSocketDlg::OnButtonDelete()
{
// TODO: Add your control notification handler code here
CSingleLock slock(&m_Mutex);
slock.Lock(); if(m_pSocket!=NULL)
{
m_pSocket->ShutDown();
m_pSocket->Close();
delete m_pSocket;
m_pSocket=NULL;
}
slock.Unlock();}
hThrds=CreateThread(NULL,0,SocketThread,(LPVOID)(this),0,NULL);
是要向另外一个线程传递一个MFC的窗体对象,非常典型的错误。
看以前的帖子吧,对这个问题将的比较多了。
MSG msg;
if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (GetMessage(&msg, NULL, 0, 0 ) != -1)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
这样的消息派送代码
如果你一定要用多线程,建议SOCKET API。
虽说烦了点,但是典型的代码网上多的是,你靠过来就可以了。
{
if (nErrorCode == 0)
{
Accept(m_AcceptSocket);
m_pEThread = new CEThread(m_AcceptSocket.m_hSocket);
m_pEThread->CreateThread();
m_AcceptSocket.Detach();
...
}CEThread::CEThread(SOCKET sock)
{
m_hSock = sock;
...
}
BOOL CEThread::InitInstance()
{
m_Socket.Attach(m_hSock);
...
}
[email protected]
在多线程中启动的SOCKET只能发,而不能接受。
请问是怎么回事?????????
你跟踪会发现是在lookuphandle出错
解决办法:在每个使用socket的线程一开始调用AfxSocketInit,要使用别的线程的socket要先detach,要用的attach
everandforever(Forever)已经给出解决办法了
具体参见Q193101(查msdn)