初学重叠I/O就遇到这样的问题;弄了好几天也不明白是怎么回事?
整个代码如下,然后通过客户端给该服务器端发送字符串,发送字符串第一次成功!发送字符串第二次成功!发送第三次的时候就收不到了;
运行过程同时发现WSAGetOverlappedResult()函数返回值是10014;
也不知道哪里出了问题?请大侠们给予测试或者指点;#include "stdafx.h"
#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT  5150
#define MSGSIZE  1024
typedef struct
{
    WSAOVERLAPPED overlap;
    WSABUF        Buffer;
    char          szMessage[MSGSIZE];
    DWORD         NumberOfBytesRecvd;
    DWORD         Flags;
} PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
int                     g_iTotalConn = 0;
SOCKET                  g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT                g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
LPPER_IO_OPERATION_DATA g_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS];
DWORD WINAPI WorkerThread(LPVOID lpParam);
void Cleanup(int index);int main(int argc, char* argv[])
{
    WSADATA wsaData;
    SOCKET sListen, sClient;
    SOCKADDR_IN local, client;
    DWORD dwThreadId;
    int iAddrSize = sizeof(SOCKADDR_IN);
    // Initialize windows socket library
    WSAStartup(0x0202, &wsaData);
    // Create listening socket
    sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    // Bind
    local.sin_family = AF_INET;
    local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    local.sin_port = htons(PORT);
    bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN)); 
    // Listen
    listen(sListen, 3);
    // Create worker thread
    CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
    while (TRUE)
    {
        // Accept a connection
        sClient = accept(sListen, (struct sockaddr *)&client, &iAddrSize);
        printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));       
        g_CliSocketArr[g_iTotalConn] = sClient;
        // Associate a PER_IO_OPERATION_DATA structure
        g_pPerIoDataArr[g_iTotalConn] = (LPPER_IO_OPERATION_DATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PER_IO_OPERATION_DATA));        g_pPerIoDataArr[g_iTotalConn]->Flags=0;
        g_pPerIoDataArr[g_iTotalConn]->Buffer.len = MSGSIZE;
        g_pPerIoDataArr[g_iTotalConn]->Buffer.buf = g_pPerIoDataArr[g_iTotalConn]->szMessage;
        g_CliEventArr[g_iTotalConn] = g_pPerIoDataArr[g_iTotalConn]->overlap.hEvent = WSACreateEvent();
        // Launch an asynchronous operation
        WSARecv(g_CliSocketArr[g_iTotalConn],
            &g_pPerIoDataArr[g_iTotalConn]->Buffer,
            1,
            &g_pPerIoDataArr[g_iTotalConn]->NumberOfBytesRecvd,
            &g_pPerIoDataArr[g_iTotalConn]->Flags,
            &g_pPerIoDataArr[g_iTotalConn]->overlap,
            NULL);
        g_iTotalConn++;
    }
   
    closesocket(sListen);
    WSACleanup();
    return 0;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
    //unsigned char first[128]={0};
    int ret, index;
    BOOL bResult = TRUE;
    DWORD         returnValue;
    DWORD cbTransferred;    char          buffBack[3]="abc";
    DWORD         dwBytes=0,dwFlags=0;
    WSABUF        DataBuf; 
    //ZeroMemory(&wsaBuf,sizeof(WSABUF));
    DataBuf.len=3;
    DataBuf.buf=buffBack;
    while (TRUE)
    {
        ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
        if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
        {
            continue;
        }
        index = ret - WSA_WAIT_EVENT_0;
        bResult =WSAResetEvent(g_CliEventArr[index]);
         if (bResult == FALSE) {
            wprintf(L"WSAResetEvent failed with error = %d\n", WSAGetLastError());
        }
        bResult =WSAGetOverlappedResult(g_CliSocketArr[index],
            &g_pPerIoDataArr[index]->overlap,
            &cbTransferred,
            TRUE,
            &g_pPerIoDataArr[g_iTotalConn]->Flags);
        if (bResult == FALSE) {
            wprintf(L"WSAGetOverlappedResult failed with error = %d\n", WSAGetLastError());
        }
        if (cbTransferred == 0)
        {
            // The connection was closed by client
            Cleanup(index);
        }
        else
        {
            WSARecv(g_CliSocketArr[index],
                &g_pPerIoDataArr[index]->Buffer,
                1,
                &g_pPerIoDataArr[index]->NumberOfBytesRecvd,
                &g_pPerIoDataArr[index]->Flags,
                &g_pPerIoDataArr[index]->overlap,
                NULL);
         
             memset(&(g_pPerIoDataArr[index]->overlap), '\0', sizeof(WSAOVERLAPPED));//将overlapped结构清空
             returnValue=WSASend(g_CliSocketArr[index], &DataBuf, 1, &dwBytes, dwFlags, &g_pPerIoDataArr[index]->overlap, NULL);
             printf("%s",g_pPerIoDataArr[index]->Buffer.buf);
        }
    }
   
    return 0;
}
void Cleanup(int index)
{
    closesocket(g_CliSocketArr[index]);
    WSACloseEvent(g_CliEventArr[index]);
    HeapFree(GetProcessHeap(), 0, g_pPerIoDataArr[index]);
    if (index < g_iTotalConn-1)
    {
        g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn-1];
        g_CliEventArr[index] = g_CliEventArr[g_iTotalConn-1];
        g_pPerIoDataArr[index] = g_pPerIoDataArr[g_iTotalConn-1];
    }
   
    g_pPerIoDataArr[--g_iTotalConn] = NULL;
}

解决方案 »

  1.   

    GetLastError返回10014  
    (10014-系统检测到在一个调用中尝试使用指针参数时的无效指针地址。 )
      

  2.   

    overlap最好不要同一段时间内多次使用
    要等到IO完成后才能重用
    并且要memset一下,但要注意那个hEvent成员不能置NULLWSARecv后立即又WSASend,用的是同一个overlap
    而且memset(&(g_pPerIoDataArr[index]->overlap), '\0', sizeof(WSAOVERLAPPED));//将overlapped结构清空
    这句把overlap.hEvent也置NULL了想有收发
    可以再增加一线程,代码照搬recv的
    或者将原来的全局变量修改下

    WSAEVENT                g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
    LPPER_IO_OPERATION_DATA g_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS];
    改成
    WSAEVENT                g_CliEventArr[2][MAXIMUM_WAIT_OBJECTS];
    LPPER_IO_OPERATION_DATA g_pPerIoDataArr[2][MAXIMUM_WAIT_OBJECTS];
      

  3.   

    主要一点是保证你的重叠结构体有效,在使用过程中不会被释放或者被破坏
    http://blog.csdn.net/visualeleven/article/details/5991743
      

  4.   


    for(int i = dwIndex; i < g_nIndex; i++)  
            {  
                dwIndex = WSAWaitForMultipleEvents(1, &g_event[dwIndex], TRUE, INFINITE, FALSE);  
                if(WSA_WAIT_FAILED == dwIndex)  
                {  
                    continue;  
                }  你好;
    其中WSAWaitForMultipleEvents()的第一个参数1在这里有何预意?
      

  5.   

    等待该句柄的事件对象signal状态
      

  6.   


    #include "stdafx.h"
    #include <WINSOCK2.H>
    #include <stdio.h>
    #pragma comment(lib, "ws2_32.lib")
    #define PORT     2023
    #define MSGSIZE  32
    typedef enum _OPERATION_INFO  
    {  
        OP_NULL,  
        OP_READ,  
        OP_WRITE  
    }OPERATIONINFO; 
    typedef struct
    {
        WSAOVERLAPPED overlap;
        WSABUF        wsaBuf;
        char   szBuf[MSGSIZE]; 
        DWORD         NumberOfBytesRecvd;
        DWORD         Flags;
        SOCKET        sock;  
        SOCKADDR_IN   addr; 
        OPERATIONINFO nOpType;  
    } PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
    int                     g_iTotalConn = 0;
    SOCKET                  g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
    WSAEVENT                g_CliEventArr[MAXIMUM_WAIT_OBJECTS]={0};
    LPPER_IO_OPERATION_DATA g_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS]={0};
    BOOL g_bExitThread = FALSE;  
    DWORD WINAPI WorkerThread(LPVOID lpParam);
    void Cleanup(int index);
    int main(int argc, char* argv[])
    {
        DWORD dwTrans = 0;  
        DWORD dwFlags = 0;  
        HANDLE hThread;
        WSADATA wsaData;
        SOCKET sListen, sClient;
        SOCKADDR_IN local, client;
        DWORD dwThreadId;
        int iAddrSize = sizeof(SOCKADDR_IN);
    if(0 != WSAStartup(MAKEWORD(2, 2), &wsaData))  
        {  
            printf("WSAStartup failed with error code: %d/n", GetLastError());  
            return 0;  
        } 
         sListen = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
    if(INVALID_SOCKET == sListen) 
    {  
            printf("socket failed with error code: %d\n", WSAGetLastError());  
            WSACleanup();  
            return 0;  
        }
        local.sin_family = AF_INET;
        local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
        local.sin_port = htons(PORT);
    if(SOCKET_ERROR == bind(sListen, (LPSOCKADDR)&local, sizeof(local)))  
        {
    printf("bind failed with error code: %d/n", WSAGetLastError());  
            closesocket(sListen);  
            sListen = INVALID_SOCKET;  
            WSACleanup();  
            return 0;  
    }
    if(SOCKET_ERROR == listen(sListen, 5)) 
    {
        printf("listen failed with error code: %d\n", WSAGetLastError());  
            closesocket(sListen);  
            sListen = INVALID_SOCKET;  
            WSACleanup();  
            return 0;  
    }
        hThread=CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
        if(NULL == hThread)  
        {  
            printf("CreateThread failed with error code: %d\n", GetLastError());  
            closesocket(sListen);  
            sListen = INVALID_SOCKET;  
            WSACleanup();  
            return 0;  
        }  
        printf("Server start listen and wait for client to connect ...\n");  
        while (TRUE)
        {
    if(g_iTotalConn >= WSA_MAXIMUM_WAIT_EVENTS)  
            {  
                printf("Too many connect, wait for disconnect .../n");  
                continue;  
            } 
            sClient = accept(sListen, (struct sockaddr *)&client, &iAddrSize);
             if(INVALID_SOCKET == sClient)  
            {  
                printf("accept failed with error code: %d\n", WSAGetLastError());  
                continue;  
            } 
    printf("<IP: %s, Port: %d> client come in.\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));       
            g_pPerIoDataArr[g_iTotalConn] = (LPPER_IO_OPERATION_DATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PER_IO_OPERATION_DATA));
    g_pPerIoDataArr[g_iTotalConn]->sock = sClient;
    memcpy(&g_pPerIoDataArr[g_iTotalConn]->addr, &client, sizeof(client));
    g_pPerIoDataArr[g_iTotalConn]->szBuf[0]=0;
    g_pPerIoDataArr[g_iTotalConn]->wsaBuf.len = MSGSIZE;
            g_pPerIoDataArr[g_iTotalConn]->wsaBuf.buf = g_pPerIoDataArr[g_iTotalConn]->szBuf;
        g_CliEventArr[g_iTotalConn] = g_pPerIoDataArr[g_iTotalConn]->overlap.hEvent = WSACreateEvent(); 
    g_pPerIoDataArr[g_iTotalConn]->nOpType = OP_READ; 
      if(SOCKET_ERROR == WSARecv(g_pPerIoDataArr[g_iTotalConn]->sock, 
    &(g_pPerIoDataArr[g_iTotalConn]->wsaBuf),
    1, &dwTrans, &dwFlags,
    (LPWSAOVERLAPPED)&(g_pPerIoDataArr[g_iTotalConn]->overlap),
    NULL))  
    {
        if(ERROR_IO_PENDING != WSAGetLastError())  
                {  
                    printf("WSARecv failed with error code: %d\n", WSAGetLastError());  
                    closesocket(g_pPerIoDataArr[g_iTotalConn]->sock);  
    HeapFree(GetProcessHeap(), 0, g_pPerIoDataArr                g_pPerIoDataArr[g_iTotalConn] = NULL;  
                    continue;  
                }  
    }
            g_iTotalConn++;
        }
        g_bExitThread = TRUE; 
        WaitForSingleObject(hThread, INFINITE);  
        CloseHandle(hThread);  
        closesocket(sListen);
        WSACleanup();
        return 0;
    }
    DWORD WINAPI WorkerThread(LPVOID lpParam)
    {
        DWORD  dwIndex;
        int i;
    BOOL bRet;
    DWORD dwTrans = 0;
        char          buffBack[3]="abc";
        DWORD         dwBytes=0,dwFlags=0;
        DataBuf.len=3;
        DataBuf.buf=buffBack;
        while (!g_bExitThread)
        {
            dwIndex = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
            if(WSA_WAIT_FAILED == dwIndex || WSA_WAIT_TIMEOUT == dwIndex)  
            {  
                continue;  
            } 
            dwIndex -= WSA_WAIT_EVENT_0;

            for(i = dwIndex; i < g_iTotalConn; i++)  
            {
                dwIndex = WSAWaitForMultipleEvents(1, &g_CliEventArr[dwIndex], TRUE, INFINITE, FALSE);  
    if(WSA_WAIT_FAILED == dwIndex)  
                {  
                    continue;  
                } 
    dwIndex -= WSA_WAIT_EVENT_0;  
                WSAResetEvent(g_CliEventArr[dwIndex]);
        bRet = WSAGetOverlappedResult(g_pPerIoDataArr[dwIndex]->sock, &(g_pPerIoDataArr[dwIndex]->overlap), &dwTrans, FALSE, &dwFlags);  
                if(bRet)  
                {  
                  if(dwTrans > 0)  
                  { 
      switch(g_pPerIoDataArr[dwIndex]->nOpType)  
                      {
       case OP_READ:  
                            {
     
    printf("recv client <%s:%d> data: %s\n", inet_ntoa(g_pPerIoDataArr[dwIndex]->addr.sin_addr), ntohs(g_pPerIoDataArr[dwIndex]->addr.sin_port), g_pPerIoDataArr[dwIndex]->szBuf);  
                                g_pPerIoDataArr[dwIndex]->nOpType = OP_WRITE;  
      
    memset(&(g_pPerIoDataArr[dwIndex]->overlap), 0, sizeof(g_pPerIoDataArr[dwIndex]->overlap));
        if(SOCKET_ERROR == WSASend(g_pPerIoDataArr[dwIndex]->sock, &(g_pPerIoDataArr[dwIndex]->wsaBuf), 1, &dwTrans, dwFlags, &(g_pPerIoDataArr[dwIndex]->overlap), NULL))  
                                {  
                                    if(ERROR_IO_PENDING != WSAGetLastError())  
                                    {  
                                        printf("WSASend failed with error code: %d/n", WSAGetLastError());  
                                        continue;  
                                    }  
                                }
    }
        break;
       case OP_WRITE:  
                            { 
     
     g_pPerIoDataArr[dwIndex]->nOpType = OP_READ;  
                   memset(&(g_pPerIoDataArr[dwIndex]->overlap), 0, sizeof(g_pPerIoDataArr[dwIndex]->overlap));  
                   memset(g_pPerIoDataArr[dwIndex]->szBuf, 0, sizeof(g_pPerIoDataArr[dwIndex]->szBuf));  
                   dwFlags = 0;  
                 g_pPerIoDataArr[dwIndex]->wsaBuf.buf = g_pPerIoDataArr[dwIndex]->szBuf;  
                 dwTrans = g_pPerIoDataArr[dwIndex]->wsaBuf.len = MSGSIZE;  
                 if(SOCKET_ERROR == WSARecv(g_pPerIoDataArr[dwIndex]->sock, &(g_pPerIoDataArr[dwIndex]->wsaBuf), 1, &dwTrans, &dwFlags, &(g_pPerIoDataArr[dwIndex]->overlap), NULL))  
                                {  
                                    if(ERROR_IO_PENDING != WSAGetLastError())  
                                    {  
                                        printf("WSARecv failed with error code: %d/n", WSAGetLastError());  
                                        continue;  
                                    }  
                                } 
    }
    break;
        default:  
                            break;    }
      }
       else  
                    {  
                        printf("client <%s : %d> leave.\n", inet_ntoa(g_pPerIoDataArr[dwIndex]->addr.sin_addr), ntohs(g_pPerIoDataArr[dwIndex]->addr.sin_port));  
                        closesocket(g_pPerIoDataArr[dwIndex]->sock);  
                        WSACloseEvent(g_CliEventArr[dwIndex]);  
      HeapFree(GetProcessHeap(), 0, g_pPerIoDataArr[g_iTotalConn]);
                   g_pPerIoDataArr[g_iTotalConn] = NULL;
                        for(  i= dwIndex; i<g_iTotalConn-1; i++)  
                        {  
                            g_CliEventArr[i] = g_CliEventArr[i+1];  
                            g_pPerIoDataArr[i] = g_pPerIoDataArr[i+1];  
                        }  
                        g_iTotalConn--;  
                    }
    }
     else  
                {  
                    printf("WSAGetOverlappedResult failed with error: %d\n", WSAGetLastError());  
                } 
    }
        }
    printf("Server to exit ... \n");  
       
        return 0;
    }
    第一次可以接收到字符串,第二次就无法接收到字符串;这是什么原因?
      

  7.   

    保证你的重叠结构体有效,在使用过程中不会被释放或者被破坏
    http://blog.csdn.net/visualeleven/article/details/5991743
      

  8.   

    ”memset(&(g_pPerIoDataArr[index]->overlap), '\0', sizeof(WSAOVERLAPPED));//将overlapped结构清空
    这句把overlap.hEvent也置NULL了“
    既然清空了,那我就重新:
    g_pPerIoDataArr[Index]->overlap.hEvent = g_CliEventArr[Index];