DWORD dwListenThreadId;
hThread[0] = CreateThread(NULL, 0, ListenThread, NULL, 0, &dwListenThreadId);
DWORD dwWorkThreadId;
hThread[1] = CreateThread(NULL, 0, WorkThread, NULL, 0, &dwWorkThreadId);
DWORD dwLogicThreadId;DWORD WINAPI CServerDlg::ListenThread(LPVOID)
{
WSADATA wsaData; int nRet; nRet=WSAStartup(MAKEWORD(2,2),&wsaData);
if(nRet!=0)
{
AfxMessageBox("Load winsock2 failed");
WSACleanup();
return -1;
}
SOCKET sockListen;
sockListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //创建服务套接字(TCP)
if(sockListen == INVALID_SOCKET)
{
AfxMessageBox("Create Listening Socket Fail!");
}
// BOOL bReuseaddr=TRUE;
// setsockopt(sockListen,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); SOCKADDR_IN ServerAddr; //分配端口及协议族并绑定 ServerAddr.sin_family=AF_INET;
ServerAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
ServerAddr.sin_port=htons(DE_PORT); nRet=bind(sockListen,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr)); // 绑定套接字 if(nRet==SOCKET_ERROR)
{
AfxMessageBox("Bind Socket Fail!");
closesocket(sockListen);
WSACleanup();
return -1;
} nRet=listen(sockListen,1); //开始监听,并设置监听客户端数量
if(nRet==SOCKET_ERROR)
{
AfxMessageBox("Listening Fail!");
return -1;
} SOCKADDR_IN ClientAddr; // 定义一个客户端得地址结构作为参数
int addr_length=sizeof(ClientAddr);
while(true)
{
if(bThreadRun)
{
sockNew = accept( // 接收连入的客户端
sockListen,
(SOCKADDR*)&ClientAddr,
&addr_length
); if(sockNew == INVALID_SOCKET) // 检测SOCKET是否有效
{
AfxMessageBox("Accept Connection failed!");
continue;
} CString strSock;
strSock.Format("SOCKET编号:%d",sockNew); ::SendMessage(
hWnd,
WM_MSG_NEW_SOCKET,
(LPARAM)(LPCTSTR)strSock,
(LPARAM)(LPCTSTR)"连接到服务器"
);
bNewSocket = TRUE;
}
else
{
break;
}
}
return 0;
}
DWORD WINAPI CServerDlg::WorkThread(LPVOID)
{
LPPER_IO_OPERATION_DATA lpPerIOData = NULL; while(true)
{
if(bThreadRun)
{
if(bNewSocket)
{
lpPerIOData = (LPPER_IO_OPERATION_DATA)HeapAlloc(
GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PER_IO_OPERATION_DATA));
lpPerIOData->Buffer.len = SZ_HEAD;
lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
lpPerIOData->sClient = sockNew;
lpPerIOData->nTotal = 0;
lpPerIOData->str = ""; //投递接收请求
if(WSARecv(lpPerIOData->sClient,
&lpPerIOData->Buffer,
1,
&lpPerIOData->NumberOfBytesRecvd,
&lpPerIOData->Flags,
&lpPerIOData->overlap,
CompletionROUTINE) == SOCKET_ERROR)
{
//接收函数失败,释放内存
if(WSAGetLastError() != WSA_IO_PENDING)
{
closesocket(lpPerIOData->sClient);
HeapFree(GetProcessHeap(), 0, lpPerIOData);
AfxMessageBox("WSARecv函数失败!");
continue;
}
}
bNewSocket = false;
} SleepEx(1000, TRUE);
}
else
break;
} return 0;
}下面UI按钮函数
void CServerDlg::OnCancel()
{
bThreadRun = false;
::WaitForSingleObject(hThread[0],INFINITE);
::CloseHandle(hThread[0]);
::WaitForSingleObject(hThread[1],INFINITE);
::CloseHandle(hThread[1]);
closesocket(sockNew);
WSACleanup();
CDialog::OnCancel();
}
不知道为什么线程就是不退出,一点击退出按钮,程序就没有反应了,难道是accept阻塞了线程?请各位大侠帮忙!!!
hThread[0] = CreateThread(NULL, 0, ListenThread, NULL, 0, &dwListenThreadId);
DWORD dwWorkThreadId;
hThread[1] = CreateThread(NULL, 0, WorkThread, NULL, 0, &dwWorkThreadId);
DWORD dwLogicThreadId;DWORD WINAPI CServerDlg::ListenThread(LPVOID)
{
WSADATA wsaData; int nRet; nRet=WSAStartup(MAKEWORD(2,2),&wsaData);
if(nRet!=0)
{
AfxMessageBox("Load winsock2 failed");
WSACleanup();
return -1;
}
SOCKET sockListen;
sockListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //创建服务套接字(TCP)
if(sockListen == INVALID_SOCKET)
{
AfxMessageBox("Create Listening Socket Fail!");
}
// BOOL bReuseaddr=TRUE;
// setsockopt(sockListen,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); SOCKADDR_IN ServerAddr; //分配端口及协议族并绑定 ServerAddr.sin_family=AF_INET;
ServerAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
ServerAddr.sin_port=htons(DE_PORT); nRet=bind(sockListen,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr)); // 绑定套接字 if(nRet==SOCKET_ERROR)
{
AfxMessageBox("Bind Socket Fail!");
closesocket(sockListen);
WSACleanup();
return -1;
} nRet=listen(sockListen,1); //开始监听,并设置监听客户端数量
if(nRet==SOCKET_ERROR)
{
AfxMessageBox("Listening Fail!");
return -1;
} SOCKADDR_IN ClientAddr; // 定义一个客户端得地址结构作为参数
int addr_length=sizeof(ClientAddr);
while(true)
{
if(bThreadRun)
{
sockNew = accept( // 接收连入的客户端
sockListen,
(SOCKADDR*)&ClientAddr,
&addr_length
); if(sockNew == INVALID_SOCKET) // 检测SOCKET是否有效
{
AfxMessageBox("Accept Connection failed!");
continue;
} CString strSock;
strSock.Format("SOCKET编号:%d",sockNew); ::SendMessage(
hWnd,
WM_MSG_NEW_SOCKET,
(LPARAM)(LPCTSTR)strSock,
(LPARAM)(LPCTSTR)"连接到服务器"
);
bNewSocket = TRUE;
}
else
{
break;
}
}
return 0;
}
DWORD WINAPI CServerDlg::WorkThread(LPVOID)
{
LPPER_IO_OPERATION_DATA lpPerIOData = NULL; while(true)
{
if(bThreadRun)
{
if(bNewSocket)
{
lpPerIOData = (LPPER_IO_OPERATION_DATA)HeapAlloc(
GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PER_IO_OPERATION_DATA));
lpPerIOData->Buffer.len = SZ_HEAD;
lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
lpPerIOData->sClient = sockNew;
lpPerIOData->nTotal = 0;
lpPerIOData->str = ""; //投递接收请求
if(WSARecv(lpPerIOData->sClient,
&lpPerIOData->Buffer,
1,
&lpPerIOData->NumberOfBytesRecvd,
&lpPerIOData->Flags,
&lpPerIOData->overlap,
CompletionROUTINE) == SOCKET_ERROR)
{
//接收函数失败,释放内存
if(WSAGetLastError() != WSA_IO_PENDING)
{
closesocket(lpPerIOData->sClient);
HeapFree(GetProcessHeap(), 0, lpPerIOData);
AfxMessageBox("WSARecv函数失败!");
continue;
}
}
bNewSocket = false;
} SleepEx(1000, TRUE);
}
else
break;
} return 0;
}下面UI按钮函数
void CServerDlg::OnCancel()
{
bThreadRun = false;
::WaitForSingleObject(hThread[0],INFINITE);
::CloseHandle(hThread[0]);
::WaitForSingleObject(hThread[1],INFINITE);
::CloseHandle(hThread[1]);
closesocket(sockNew);
WSACleanup();
CDialog::OnCancel();
}
不知道为什么线程就是不退出,一点击退出按钮,程序就没有反应了,难道是accept阻塞了线程?请各位大侠帮忙!!!
除了使用异步socket之外,一种比较粗暴的做法是在关闭时,让另一个线程把server socket给强行close掉,那样一来,accept应该就回返回了。