服务端代码:
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("WSAStartup errors!\n");
return;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return;
} SOCKET sockSvr = WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, WSA_FLAG_OVERLAPPED);
if(INVALID_SOCKET == sockSvr)
{
printf("WSASocket errors!\n");
return;
}
SOCKADDR_IN addrSvr;
ZeroMemory(&addrSvr, sizeof(SOCKADDR_IN));
addrSvr.sin_family = AF_INET;
addrSvr.sin_port = htons(8080);
addrSvr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int nRet = bind(sockSvr, (SOCKADDR*)&addrSvr, sizeof(SOCKADDR));
if(SOCKET_ERROR == nRet)
{
printf("bind errors!\n");
return;
}
nRet = listen(sockSvr, 500);//500:max number of connect request
if(SOCKET_ERROR == nRet)
{
printf("listen errors!\n");
return;
} HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
if(!hCompletionPort)
{
printf("CreateIoCompletionPort errors!\n");
return;
}
SYSTEM_INFO SystemInfo;
UINT i = 0;
DWORD dwThreadID = 0;
GetSystemInfo(&SystemInfo);
for(i=0; i<SystemInfo.dwNumberOfProcessors*2; i++)
{
HANDLE ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, hCompletionPort, 0, &dwThreadID);
if(ThreadHandle == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return;
}
CloseHandle(ThreadHandle);
}
while(true)
{
SOCKADDR_IN addrAccept;
ZeroMemory(&addrAccept, sizeof(SOCKADDR_IN));
int nSockLen = sizeof(SOCKADDR);
SOCKET sockAccept = WSAAccept(sockSvr, (SOCKADDR*)&addrAccept, &nSockLen, 0, 0);
if(INVALID_SOCKET == sockSvr)
{
printf("WSAAccept errors!\n");
return;
}
if(NULL==CreateIoCompletionPort((HANDLE)sockAccept, hCompletionPort, (DWORD)sockSvr, 0))
{
printf("CreateIoCompletionPort errors!\n");
return;
}


OVERLAPPEDPLUS* pOlp = new OVERLAPPEDPLUS;
ZeroMemory(pOlp, sizeof(OVERLAPPEDPLUS));
ZeroMemory(&(pOlp->ol), sizeof(OVERLAPPED));
pOlp->socket = sockAccept;
pOlp->dwFlags = 0;
pOlp->wsaBuf.buf = pOlp->pBuf;
pOlp->wsaBuf.len = 4096;
pOlp->nOpCode = FD_READ;
nRet = WSARecv(pOlp->socket, &(pOlp->wsaBuf), 1, &(pOlp->dwBytes), &(pOlp->dwFlags), &(pOlp->ol), NULL);
if(SOCKET_ERROR == nRet)
{
if(WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return;
}
}
}
return;
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE hCompletionPort = (HANDLE) CompletionPortID;
void* re;
DWORD berByte;
OVERLAPPED* pOl;
while(TRUE)
{
BOOL bRet = GetQueuedCompletionStatus(hCompletionPort, &berByte, (LPDWORD)&re, (LPOVERLAPPED*)&pOl, INFINITE);
if(!bRet)
{
printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
return FALSE;
}
if(0 == berByte)
{
printf("DGFDGDGF\n");
return FALSE;
}
OVERLAPPEDPLUS* pOlp = (OVERLAPPEDPLUS*) pOl;
switch(pOlp->nOpCode)
{
case FD_READ:
printf("%s\n", pOlp->wsaBuf.buf);
break;
default:
printf("no data!!\n");
}
pOlp->nOpCode = FD_READ;
WSARecv(pOlp->socket, &(pOlp->wsaBuf), 1, &(pOlp->dwBytes), &(pOlp->dwFlags), &(pOlp->ol), NULL);
}
return TRUE;
}客户端:
....  因为客户端的代码,就是普通的一般这些连接代码,没用得什么IOCP相关函数,
现在我要问的问题是:如果我把客户端完全关闭(结束客户端程序的进程),那么我在启动客户端在连接服务端,就没问题.如果只是在客户端closesocket(sClient),客户端肯定是不能与服务端通信了,但是我在连接服务端,就连不上了,连起没反应,只能把整个客户端关闭后,在启动,在连接才OK,这是为什么,

解决方案 »

  1.   

    连接不上,WSAGetLastError获取查看下错误代码。
    MSDN上说
    If SO_DONTLINGER enabled (the default setting) it always returns immediately – connection is gracefully closed in the background. 
    If SO_LINGER enabled with a zero time-out: it always returns immediately - connection is reset/terminated. 
    If SO_LINGER enabled with nonzero time-out: 
    with blocking socket it blocks until all data sent or time-out expires. 
    with nonblocking socket it returns immediately that indicates failure. 
      

  2.   

    你需要在服务端上面也关闭客户端连接上来的socket