完成端口(I/O completion),哪里出错了?
xue23 2005-08-10 04:53:26 是不是不能用send()和完成端口工作?
大家看看我的代码
服务器端:
HANDLE hEvent = NULL;
HANDLE hIOCP = NULL;
SOCKET sockListen = INVALID_SOCKET;
UINT hListen;
UINT hRead;
UINT __stdcall ListenThread(void * p)
{
int nLen;
int nRet;
DWORD dwRet;
SOCKADDR_IN sa;
SOCKET csocket;
while(1)
{
Sleep(10);
dwRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE, 100, FALSE);
if(dwRet == WSA_WAIT_TIMEOUT)
continue;
WSANETWORKEVENTS events;
nRet = WSAEnumNetworkEvents(sockListen, hEvent, &events);
if(nRet == SOCKET_ERROR)
{
break;
}
if(events.lNetworkEvents & FD_ACCEPT)
{
if(events.iErrorCode[FD_ACCEPT_BIT] == 0)
{
nLen = sizeof(sa);
csocket = WSAAccept(sockListen, (sockaddr*)&sa, &nLen, 0, 0);
Sleep(10);
if(csocket == SOCKET_ERROR)
continue;
//OVERLAPPED *pOverLapped = new OVERLAPPED;
HANDLE h = CreateIoCompletionPort((HANDLE) csocket, hIOCP, (DWORD)csocket, 0);
if(h != hIOCP)
continue;
// --- DavidTr: Slide 16 -------------------------------------------
//
// Disable send bufferring on the socket. Setting SO_SNDBUF
// to 0 causes winsock to stop bufferring sends and perform
// sends directly from our buffers, thereby reducing CPU
// usage.
//
int zero = 0;
nRet = setsockopt( csocket, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero) );
if ( nRet == SOCKET_ERROR )
{
break;
}
}
else
{
break;
}
}
}
return 0;
}
UINT __stdcall ReadThread(void * p)
{
DWORD numberOfBytes;
DWORD completionKey;
OVERLAPPED ol;
LPOVERLAPPED lpOverlapped = &ol;
BOOL bIORet;
while(1)
{
Sleep(10);
bIORet = GetQueuedCompletionStatus(hIOCP, &numberOfBytes, &completionKey, &lpOverlapped, INFINITE);
DWORD dwIOError = GetLastError();
if(!bIORet && dwIOError != WAIT_TIMEOUT)
{
break;
}
}
return 0;
}
int CreateSocket()
{
sockListen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, NULL, WSA_FLAG_OVERLAPPED);
if(sockListen == INVALID_SOCKET)
{
return WSAGetLastError();
}
hEvent = WSACreateEvent();
if(hEvent == WSA_INVALID_EVENT)
{
return WSAGetLastError();
}
int nRet = WSAEventSelect(sockListen, hEvent, FD_ACCEPT);
if(nRet == SOCKET_ERROR)
{
return WSAGetLastError();
}
SOCKADDR_IN sa;
sa.sin_family = AF_INET;
sa.sin_addr.S_un.S_addr = INADDR_ANY;
sa.sin_port = htons(8886);
nRet = bind(sockListen, (sockaddr*)&sa, sizeof(sa));
if(nRet == SOCKET_ERROR)
{
return WSAGetLastError();
}
nRet =listen(sockListen, 5);
if(nRet == SOCKET_ERROR)
{
return WSAGetLastError();
}
return 0;
}
int CreateIOCP()
{
// SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
// if(sock == INVALID_SOCKET)
// return -1;
// SYSTEM_INFO si;
// ::GetSystemInfo(& si);
// DWORD dwNumberOfWorkers = 2 * si.dwNumberOfProcessors + 2;
hIOCP = CreateIoCompletionPort((HANDLE)INVALID_HANDLE_VALUE, NULL, 0, 0);
if(!hIOCP)
{
return -2;
}
// closesocket(sock);
return 0;
}
int main(int argc, char* argv[])
{
WORD rver = MAKEWORD(2, 2);
WSADATA wsaData;
if(0 != WSAStartup(rver, &wsaData))
return -1;
if(HIBYTE(wsaData.wVersion) !=2 || HIBYTE(wsaData.wVersion != 2))
return -1;
if(0 != CreateIOCP())
return -2;
if(0 != CreateSocket())
return -3;
UINT id;
hRead = _beginthreadex(NULL, 0, ReadThread, NULL, 0, &id);
hListen = _beginthreadex(NULL, 0, ListenThread, NULL, 0, &id);
::WaitForSingleObject((HANDLE)hListen, INFINITE);
return 0;
}
客户端:
int main(int argc, char* argv[])
{
WSADATA wsaData;
WORD rVersion;
int nRet;
rVersion = MAKEWORD(2, 2);
nRet = WSAStartup(rVersion, &wsaData);
if(nRet != 0)
return -1;
if(HIBYTE(wsaData.wVersion) != 2 || LOBYTE(wsaData.wVersion) != 2)
return -1;
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
if(s == INVALID_SOCKET)
return -1;
SOCKADDR_IN sa;
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("192.168.0.75");
sa.sin_port = htons(8886);
nRet = connect(s, (sockaddr*)&sa, sizeof(sa));
if(nRet != 0)
return -1;
char *buffer = "this is a test!";
while(1)
{
int nSend = send(s, buffer, strlen(buffer), 0);
if(nSend == 0)
{
break;
}
else if(nSend < 0)
{
DWORD err = WSAGetLastError();
break;
}
Sleep(1000);
}
return 0;
}