为何我的WSAAsyncSelect函数,在接受了第一个客户端连接以后,被其映射的消息函数就再也未被调用过?但是客户端提仍然提示已正确连接到服务器,但不能发送接收消息.
我的WSAAsyncSelect是这样调用的:
WSAAsyncSelect(ServerSock, AfxGetMainWnd()->m_hWnd, WM_CLIENT_ARRIAY, FD_ACCEPT);
WM_CLIENT_ARRIAY消息被映射到OnAccept函数,但其仅在第一个客户端连入时执行一次,以后再有客户端连入时就跟踪不到它执行了,是不是每次接受了客户端连接以后都要再次重析注册一次WSAAsyncSelect函数才行?
我的程序哪里有不妥之处,请各位哥哥姐姐们帮忙看看,给点意见.
我的WSAAsyncSelect是这样调用的:
WSAAsyncSelect(ServerSock, AfxGetMainWnd()->m_hWnd, WM_CLIENT_ARRIAY, FD_ACCEPT);
WM_CLIENT_ARRIAY消息被映射到OnAccept函数,但其仅在第一个客户端连入时执行一次,以后再有客户端连入时就跟踪不到它执行了,是不是每次接受了客户端连接以后都要再次重析注册一次WSAAsyncSelect函数才行?
我的程序哪里有不妥之处,请各位哥哥姐姐们帮忙看看,给点意见.
void CServerDlg::OnNetConn(WPARAM wParam, LPARAM lParam)
{
int iEvent = WSAGETSELECTEVENT(lParam);
//得到发出此事件的客户端套接字
char buf[20];
SOCKET pSock = (SOCKET)wParam;
switch(iEvent)
{
case FD_ACCEPT: //客户端连接请求
{
Thread_Data *Td = new Thread_Data;
Td->sock = pSock;
Td->pCc = new CClient();
unsigned long hHwnd;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ProcessClient,
(LPVOID)Td, CREATE_ALWAYS, &hHwnd);
break;
}
case FD_CLOSE:
break;
default: break;
}
}函数一创建完了线程就返回了呀,不存在一直处理的问题.
我的网络初始化函数是这样调用的:
bool CServerDlg::InitNetPara()
{
WORD wVersionRequested;// 定义版本信息变量
WSADATA wsaData;//定义数据信息变量
wVersionRequested = MAKEWORD(1,1);//给版本信息赋值
int ret = WSAStartup(wVersionRequested, &wsaData);
if ( ret != 0){
AfxMessageBox(_T("初始化套接字失败!"));
return FALSE;
} ServerSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ServerSocket ==INVALID_SOCKET){
AfxMessageBox(_T("创建套接字失败!"));
closesocket(ServerSocket);
WSACleanup();
return FALSE;
}
sockaddr_in sin ;
sin.sin_addr.s_addr = htons(INADDR_ANY);
sin.sin_family = AF_INET;
sin.sin_port= htons( PORT);
if( bind(ServerSocket,(const struct sockaddr*)&sin,
sizeof(sockaddr)) == SOCKET_ERROR){
AfxMessageBox(_T("绑定地址失败!"));
closesocket(ServerSocket);
WSACleanup();
return FALSE;
} WSAAsyncSelect(ServerSocket, AfxGetMainWnd()->m_hWnd , WM_CLIENT_ARRIAY, FD_ACCEPT);
listen(ServerSocket, SOMAXCONN); //监听网络事件
return true;
}
而且,你应把已连接套接口传入Td->sock,而不是把监听套接口传入Td->sock。
void CServerDlg::OnNetConn(WPARAM wParam, LPARAM lParam)
{
int iEvent = WSAGETSELECTEVENT(lParam);
//得到发出此事件的客户端套接字
char buf[20];
SOCKET pSock = (SOCKET)wParam;
switch(iEvent)
{
case FD_ACCEPT: //客户端连接请求
{
Thread_Data *Td = new Thread_Data;
Td->sock = accept(pSock,.....);
;
WSADATA wsaData;
ASSERT(WSAStartup(MAKEWORD(2,2), &wsaData)==0);
listen(hListenSocket, 5);
WSAAsyncSelect(hListenSocket, m_hWnd, WM_ACCEPT, FD_ACCEPT | FD_CLOSE);LRESULT CXxx::OnAccept(WPARAM wParam, LPARAM lParam)
{
SOCKET hClientSocket;
int nEvent = WSAGETSELECTEVENT(lParam);
switch (nEvent)
{
case FD_ACCEPT:
hClientSocket = accept(wParam, NULL, NULL);
// 发出另外一个消息事件请求
WSAAsyncSelect(hClientSocket, m_hWnd, WM_CLIENT, FD_RECV | FD_WRITE | FD_CLOSE);
break;
case FD_CLOSE:
.....
break;
default:
break;
}
return 0;
}
LRESULT CXxx::OnClient(WPARAM wParam, LPARAM lParam)
{
int nRet;
int nEvent = WSAGETSELECTEVENT(lParam);
switch (nEvent)
{
case FD_RECV:
nRet = recv(wParam, buff, sizeof(buff),......);
....
break;
case FD_WRITE:
.....
default:
...
}
return 0;
}上面是一个简单的基于异步消息的TCP服务代码框架.这样做服务器,性能比较低.
程序经修改是这样的了:
void CServerDlg::OnNetConn(WPARAM wParam, LPARAM lParam)
{
int iEvent = WSAGETSELECTEVENT(lParam);
//得到发出此事件的客户端套接字
char buf[20];
struct sockaddr sa_in;
int sa_len;
SOCKET pSock = (SOCKET)wParam;
SLinkList *node = new SLinkList;
switch(iEvent)
{
case FD_ACCEPT: //客户端连接请求
{
Thread_Data *Td = new Thread_Data;
Td->sock = WSAAccept(pSock, &sa_in, &sa_len, NULL, NULL);
Td->pCc = new CClient();
node->sock = Td->sock;
node->C_Object = Td->pCc;
unsigned long hHwnd;
node->Thread_hWnd=CreateThread(NULL, NULL,
(LPTHREAD_START_ROUTINE)ProcessClient,
(LPVOID)Td, CREATE_ALWAYS, &hHwnd);
this->LList->InsertNode(node);
break;
}
case FD_CLOSE:
this->LList->DeleteNode(pSock);
break;
default: break;
}