小弟最近自学Windows网络编程~~对于其中的一段代码不是很理解,求大神解答,小弟万分感激!!!!LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SOCKET Accept;
LPSOCKET_INFORMATION SocketInfo;
DWORD RecvBytes, SendBytes;
DWORD Flags; if (uMsg == WM_SOCKET)
{
if (WSAGETSELECTERROR(lParam))
{
printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam));
FreeSocketInformation(wParam);
}
else
{
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT: if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
{
printf("accept() failed with error %d\n", WSAGetLastError());
break;
} // Create a socket information structure to associate with the
// socket for processing I/O. CreateSocketInformation(Accept); printf("Socket number %d connected\n", Accept); WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); break; case FD_READ: SocketInfo = GetSocketInformation(wParam); // Read data only if the receive buffer is empty. if (SocketInfo->BytesRECV != 0)
{
SocketInfo->RecvPosted = TRUE;
return 0;
}
else
{
SocketInfo->DataBuf.buf = SocketInfo->Buffer;
SocketInfo->DataBuf.len = DATA_BUFSIZE; Flags = 0;
if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
&Flags, NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
FreeSocketInformation(wParam);
return 0;
}
}
else // No error so update the byte count
{
SocketInfo->BytesRECV = RecvBytes;
}
} // DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. Go ahead
// and begin writing data to the client. case FD_WRITE: SocketInfo = GetSocketInformation(wParam); if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
{
SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND; if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
FreeSocketInformation(wParam);
return 0;
}
}
else // No error so update the byte count
{
SocketInfo->BytesSEND += SendBytes;
}
} if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
{
SocketInfo->BytesSEND = 0;
SocketInfo->BytesRECV = 0; // If a RECV occurred during our SENDs then we need to post an FD_READ
// notification on the socket. if (SocketInfo->RecvPosted == TRUE)
{
SocketInfo->RecvPosted = FALSE;
PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
}
} break; case FD_CLOSE: printf("Closing socket %d\n", wParam);
FreeSocketInformation(wParam); break;
}
}
return 0;
} return DefWindowProc(hwnd, uMsg, wParam, lParam);
}主要是SOCKET Accept;这个是局部变量,对于收到 case FD_ACCEPT: if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
{
printf("accept() failed with error %d\n", WSAGetLastError());
break;
} // Create a socket information structure to associate with the
// socket for processing I/O. CreateSocketInformation(Accept); printf("Socket number %d connected\n", Accept); WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); break;时候的这句 WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);不理解。这样设置非阻塞模式监听FD_READ|FD_WRITE|FD_CLOSE有用嚒?不是窗口过程执行一遍完了之后Accept套接字应该无效了嚒
{
SOCKET Accept;
LPSOCKET_INFORMATION SocketInfo;
DWORD RecvBytes, SendBytes;
DWORD Flags; if (uMsg == WM_SOCKET)
{
if (WSAGETSELECTERROR(lParam))
{
printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam));
FreeSocketInformation(wParam);
}
else
{
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT: if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
{
printf("accept() failed with error %d\n", WSAGetLastError());
break;
} // Create a socket information structure to associate with the
// socket for processing I/O. CreateSocketInformation(Accept); printf("Socket number %d connected\n", Accept); WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); break; case FD_READ: SocketInfo = GetSocketInformation(wParam); // Read data only if the receive buffer is empty. if (SocketInfo->BytesRECV != 0)
{
SocketInfo->RecvPosted = TRUE;
return 0;
}
else
{
SocketInfo->DataBuf.buf = SocketInfo->Buffer;
SocketInfo->DataBuf.len = DATA_BUFSIZE; Flags = 0;
if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
&Flags, NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
FreeSocketInformation(wParam);
return 0;
}
}
else // No error so update the byte count
{
SocketInfo->BytesRECV = RecvBytes;
}
} // DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. Go ahead
// and begin writing data to the client. case FD_WRITE: SocketInfo = GetSocketInformation(wParam); if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
{
SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND; if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
FreeSocketInformation(wParam);
return 0;
}
}
else // No error so update the byte count
{
SocketInfo->BytesSEND += SendBytes;
}
} if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
{
SocketInfo->BytesSEND = 0;
SocketInfo->BytesRECV = 0; // If a RECV occurred during our SENDs then we need to post an FD_READ
// notification on the socket. if (SocketInfo->RecvPosted == TRUE)
{
SocketInfo->RecvPosted = FALSE;
PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
}
} break; case FD_CLOSE: printf("Closing socket %d\n", wParam);
FreeSocketInformation(wParam); break;
}
}
return 0;
} return DefWindowProc(hwnd, uMsg, wParam, lParam);
}主要是SOCKET Accept;这个是局部变量,对于收到 case FD_ACCEPT: if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
{
printf("accept() failed with error %d\n", WSAGetLastError());
break;
} // Create a socket information structure to associate with the
// socket for processing I/O. CreateSocketInformation(Accept); printf("Socket number %d connected\n", Accept); WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); break;时候的这句 WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);不理解。这样设置非阻塞模式监听FD_READ|FD_WRITE|FD_CLOSE有用嚒?不是窗口过程执行一遍完了之后Accept套接字应该无效了嚒
我觉得这里的WSAAsyncSelect效果是不是当作SendMessage的效果呀,通知主窗体WM_SOCKET事件触发吧
执行完一次,下次在Accept = accept(wParam, NULL, NULL))
HDC hDC = GetDC();
...
ReleaseDC(hDC);上面hDC是个临时变量,但如果不ReleaseDC,则会造成句柄泄漏,所以实际上,句柄是一直存在的。
换另一个模型:select,则又全集来保存着 这些句柄,FD_CLR 翻过其代码, 所做的工作简单的把句柄拿走,应该还有其他动作,比如:清楚系统内部的东西