我現在的情況是OnAccept()中的非同步事件註冊不成功,用WSAGetLastError()獲得的錯誤碼為0,用switch無法獲得錯誤訊息,下面是原代碼,My Code是在其基礎上完善的,架構大致是一樣的,
其實我想知道的是accept參數中的Socket參數是用server(正在監聽的參數)還是用訊息映射函數從Windows中獲得的SOCKET pSock = (SOCKET)wParam 這個參數,我使用server時無法重新註冊非同步事件,但使用pSock卻可以,但我根本不知道用這個pSock取得的SOCKET對象是否是合法的,雖然註冊非同步事件成功,但用戶端中斷連線時,服務端仍無任何響應,IP_EVENT 事件我已重新註冊
到訊息映射中去,用另一個訊息映射函數 IPEvent() 與其關聯,訊息映射是正常合法的
#define NETWORK_EVENT USER_MESSAGE+100 //定義網路事件
sockaddr_in clientaddr; file: //暫時存放用戶端IP地址
//自己定義訊息映射函數,將上面定義的網路事件映射到處理函數
//OnNetEvent為網路事件處理函數,它在下面定義
ON_MESSAGE(NETWORK_EVENT, OnNetEvent);
在你對話方塊中的初始化函數中調用下面的初始化網路的子函數
BOOL InitNetwork() //初始化網路
{
//初始化TCP協議
BOOL ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (ret != 0)
{
MessageBox("初始化通訊端失敗!");
return FALSE;
}
//建立伺服器端通訊端
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET)
{
MessageBox("建立通訊端失敗!");
closesocket(m_Socket);
WSACleanup();
return FALSE;
}
//綁定到本地一個連接埠上
sockaddr_in localaddr;
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(1688);
localaddr.sin_addr.s_addr = 0;
if (bind(serverSocket , (const struct sockaddr*)&localaddr,
sizeof(sockaddr)) == SOCKET_ERROR)
{
MessageBox("綁定地址失敗!");
closesocket(m_Socket);
WSACleanup();
return FALSE;
}
//註冊網路非同步事件,m_hWnd為應用程式的主對話方塊或主視窗的控制代碼
WSAAsyncSelect(serverSocket, m_hWnd, NETWORK_EVENT,
FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE);
listen(serverSocket, 5); //設定偵聽模式
return TRUE;
}
//定義網路事件的響應函數
void OnNetEvent(WPARAM wParam, LPARAM lParam)
{
//調用API函數,得到網路事件類型
int iEvent = WSAGETSELECTEVENT(lParam);
//得到發出此事件的用戶端通訊端
SOCKET pSock = (SOCKET)wParam;
switch (iEvent)
{
case FD_ACCEPT: //用戶端串連請求
{
OnAccept();
break;
}
case FD_CLOSE: //用戶端斷開事件:
{
OnClose(pSock);
break;
}
case FD_READ: //網路資料包到達事件
{
OnReceive(pSock);
break;
}
case FD_WRITE: //發送網路資料事件
{
OnSend(pSock);
break;
}
default: break;
}
}
void OnAccept(SOCET pSock) //響應用戶端串連請求函數
{
int len = sizeof(sockaddr);
//調用API函數,接受串連,並返回一個新通訊端
//還可以獲得用戶端的IP地址
SOCKET clientSocket = accept(serverSocket,
(struct sockaddr*) & clientaddr, &len);
//為新的socket註冊非同步事件,注意沒有Accept事件
if (WSAAsyncSelect(clientSocket , m_hWnd, IP_EVENT,
FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR)
{
MessageBox("註冊非同步事件失敗!");
return ;
}
//自編函數,將此用戶端的相關資訊儲存下來:通訊端、
// IP地址、登陸時間
saveClientSocket(clientSocket, clientAddr,currentTimer);
}
void OnClose(SOCET pSock)
{
//自編函數,結束與相應的用戶端的通訊,釋放相應資源並做相應處理
endClientSocket(pSock);
}
void OnSend(SOCET pSock)
{
//自編函數,在給用戶端發資料時做一些預先處理
handleOnSend(pSock);
}
void OnReceive(SOCET pSock)
{
recv(); //調用API函數,讀出網路緩衝區中的資料包
//自編函數,將此資料包和發出此資料的用戶端
//clientSocket封裝成一條網路訊息
buildNetMsg();
//自編函數,將此網路訊息放入一個訊息佇列中,由背景工作執行緒去處理
saveNetMsg();
SetEvent(); //用事件對象觸發背景工作執行緒
}