关于重叠IO代码中的疑问?解决方案

关于重叠IO代码中的疑问?
想必学习过重叠IO大侠都看过这段代码;
代码中的EventTotal为什么初始是1,而不是从0开始?
C/C++ code

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#pragma comment(lib,"ws2_32.lib") 
#define PORT 5150
#define DATA_BUFSIZE 8192

typedef struct _SOCKET_INFORMATION {
    CHAR Buffer[DATA_BUFSIZE];
    WSABUF DataBuf;
    SOCKET Socket;
    WSAOVERLAPPED Overlapped;
    DWORD BytesSEND;
    DWORD BytesRECV;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

DWORD WINAPI ProcessIO(LPVOID lpParameter);

DWORD EventTotal = 0;

WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];

LPSOCKET_INFORMATION SocketArray[WSA_MAXIMUM_WAIT_EVENTS];
CRITICAL_SECTION CriticalSection;
int main(int argc, char **argv)
{
    WSADATA wsaData;
    SOCKET ListenSocket, AcceptSocket;
    SOCKADDR_IN InternetAddr;
    DWORD Flags;
    DWORD ThreadId;
    DWORD RecvBytes;
    InitializeCriticalSection(&CriticalSection);
    if (WSAStartup((2,2),&wsaData) != 0)
    {
        printf("WSAStartup() failed with error %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }else
        printf("WSAStartup() looks nice!\n");

    if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
    {
        printf("Failed to get a socket %d\n", WSAGetLastError());
        return 1;
    } else
        printf("WSASocket() is OK lol!\n");
    InternetAddr.sin_family = AF_INET;
    InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    InternetAddr.sin_port = htons(PORT);
    if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
    {
        printf("bind() failed with error %d\n", WSAGetLastError());
        return 1;
    }else
        printf("YOu see, bind() is working!\n");
    if (listen(ListenSocket, 5))
    {
        printf("listen() failed with error %d\n", WSAGetLastError());
        return 1;
    }else
        printf("listen() is OK maa...\n");
    // Setup the listening socket for connections
    if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
    {
        printf("Failed to get a socket %d\n", WSAGetLastError());
        return 1;
    }else
        printf("WSASocket() looks OK!\n");

    if ((EventArray[0] = WSACreateEvent()) == WSA_INVALID_EVENT)
    {
        printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());
        return 1;
    }else
        printf("WSACreateEvent() is OK!\n");

    // Create a thread to service overlapped requests
    if (CreateThread(NULL, 0, ProcessIO, NULL, 0, &ThreadId) == NULL)
    {
        printf("CreateThread() failed with error %d\n", GetLastError());
        return 1;
    }else
        printf("Nothing to say, CreateThread() is OK!\n");

    EventTotal = 1;
    while(TRUE)
    { // Accept inbound connections
        if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) == INVALID_SOCKET)
        {
            printf("accept() failed with error %d\n", WSAGetLastError());
            return 1;
        }else
            printf("accept() is OK!\n");

            EnterCriticalSection(&CriticalSection);
        // Create a socket information structure to associate with the accepted socket
        if ((SocketArray[EventTotal] = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION))) == NULL)
        {
            printf("GlobalAlloc() failed with error %d\n", GetLastError());
            return 1;
        }else
            printf("GlobalAlloc() for LPSOCKET_INFORMATION is pretty fine!\n");

            // Fill in the details of our accepted socket
        SocketArray[EventTotal]->Socket = AcceptSocket;
        ZeroMemory(&(SocketArray[EventTotal]->Overlapped), sizeof(OVERLAPPED));
        SocketArray[EventTotal]->BytesSEND = 0;
        SocketArray[EventTotal]->BytesRECV = 0;
        SocketArray[EventTotal]->DataBuf.len = DATA_BUFSIZE;
        SocketArray[EventTotal]->DataBuf.buf = SocketArray[EventTotal]->Buffer;
        if ((SocketArray[EventTotal]->Overlapped.hEvent = EventArray[EventTotal] = WSACreateEvent()) == WSA_INVALID_EVENT)
        {
            printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());
            return 1;
        }else
            printf("WSACreateEvent() is OK!\n");
            // Post a WSARecv() request to to begin receiving data on the socket
            Flags = 0;
        if (WSARecv(SocketArray[EventTotal]->Socket,
        &(SocketArray[EventTotal]->DataBuf), 1, &RecvBytes, &Flags, &(SocketArray[EventTotal]->Overlapped), NULL) == SOCKET_ERROR)
        {
            if (WSAGetLastError() != ERROR_IO_PENDING)
            {
                printf("WSARecv() failed with error %d\n", WSAGetLastError());
                return 1;
            }
        }else
            printf("WSARecv() should be working!\n");

            EventTotal++;
            LeaveCriticalSection(&CriticalSection);
            // Signal the first event in the event array to tell the worker thread to
            // service an additional event in the event array
        if (WSASetEvent(EventArray[0]) == FALSE)
        {
            printf("WSASetEvent() failed with error %d\n", WSAGetLastError());
            return 1;
        }else
            printf("Don't worry, WSASetEvent() is OK!\n");
    }

}


DWORD WINAPI ProcessIO(LPVOID lpParameter)
    {
       DWORD s;
        DWORD Index;
        DWORD Flags;
        LPSOCKET_INFORMATION SI;
        DWORD BytesTransferred;
        DWORD i;
        DWORD RecvBytes, SendBytes;
    // Process asynchronous WSASend, WSARecv requests
    while(TRUE)
    {
        Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);
        if ( Index== WSA_WAIT_FAILED)
        {
            printf("WSAWaitForMultipleEvents() failed %d\n", WSAGetLastError());
            return 0;
        }else
            printf("WSAWaitForMultipleEvents() is OK!\n");
        // If the event triggered was zero then a connection attempt was made
        // on our listening socket.
        s=Index - WSA_WAIT_EVENT_0;
        if ((Index - WSA_WAIT_EVENT_0) == 0)
        {
             WSAResetEvent(EventArray[0]);
            continue;
        }
         //MessageBox(NULL,"render","dq",MB_OK);
            SI = SocketArray[Index - WSA_WAIT_EVENT_0];
            WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
        if (WSAGetOverlappedResult(SI->Socket, &(SI->Overlapped), &BytesTransferred, FALSE, &Flags) == FALSE || BytesTransferred == 0)
        {
            printf("Closing socket %d\n", SI->Socket);
            if (closesocket(SI->Socket) == SOCKET_ERROR)
            {
                printf("closesocket() failed with error %d\n", WSAGetLastError());
            }else
                printf("closesocket() is OK!\n");
            GlobalFree(SI);
            WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
            // Cleanup SocketArray and EventArray by removing the socket event handle
            // and socket information structure if they are not at the end of the arrays
            EnterCriticalSection(&CriticalSection);
            if ((Index - WSA_WAIT_EVENT_0) + 1 != EventTotal)
                for (i = Index - WSA_WAIT_EVENT_0; i < EventTotal; i++)
                {
                EventArray[i] = EventArray[i + 1];
                SocketArray[i] = SocketArray[i + 1];
                }
            EventTotal--;
            LeaveCriticalSection(&CriticalSection);
            continue;
        }
        // Check to see if the BytesRECV field equals zero. If this is so, then
        // this means a WSARecv call just completed so update the BytesRECV field
        // with the BytesTransferred value from the completed WSARecv() call.
         
        if (SI->BytesRECV == 0)
        {
            SI->BytesRECV = BytesTransferred;
            SI->BytesSEND = 0;
        }
        else
        {
            SI->BytesSEND += BytesTransferred;
        }
         
        if (SI->BytesRECV > SI->BytesSEND)
        {
            // Post another WSASend() request.
            // Since WSASend() is not guaranteed to send all of the bytes requested,
            // continue posting WSASend() calls until all received bytes are sent
            ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED));
            SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];
            SI->DataBuf.buf = SI->Buffer + SI->BytesSEND;
            SI->DataBuf.len = SI->BytesRECV - SI->BytesSEND;
            if (WSASend(SI->Socket, &(SI->DataBuf), 1, &SendBytes, 0, &(SI->Overlapped), NULL) == SOCKET_ERROR)
            {
                if (WSAGetLastError() != ERROR_IO_PENDING)
                {
                printf("WSASend() failed with error %d\n", WSAGetLastError());
                return 0;
                }
            }else
            {
               printf("WSASend() is OK!\n");
               printf("%s",SI->DataBuf.buf);
            }

        
        }else
        {
            SI->BytesRECV = 0;
            // Now that there are no more bytes to send post another WSARecv() request
            Flags = 0;
            ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED));
            SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];
            SI->DataBuf.len = DATA_BUFSIZE;
            SI->DataBuf.buf = SI->Buffer;
            if (WSARecv(SI->Socket, &(SI->DataBuf), 1, &RecvBytes, &Flags, &(SI->Overlapped), NULL) == SOCKET_ERROR)
            {
                if (WSAGetLastError() != ERROR_IO_PENDING)
                {
                printf("WSARecv() failed with error %d\n", WSAGetLastError());
                return 0;
                }
            }else
            {
                printf("WSARecv() is OK!\n");
               // printf("%s",SI->DataBuf.buf);
            }
             
            
        }
            // printf("%s",SI->DataBuf.buf);
    }
}



------解决方案--------------------
看注释吧(不懂英文?)
0号事件用作accept后通知ProcessIO线程,后面的从1开始
C/C++ code
//1.
DWORD EventTotal = 0;

//2.
if ((EventArray[0] = WSACreateEvent()) == WSA_INVALID_EVENT)
    {
        printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());
        return 1;
    }else
        printf("WSACreateEvent() is OK!\n");

//3.
// Signal the first event in the event array to tell the worker thread to
            // service an additional event in the event array
        if (WSASetEvent(EventArray[0]) == FALSE)
        {
            printf("WSASetEvent() failed with error %d\n", WSAGetLastError());
            return 1;
        }else
            printf("Don't worry, WSASetEvent() is OK!\n");

//4.
// If the event triggered was zero then a connection attempt was made
        // on our listening socket.
        s=Index - WSA_WAIT_EVENT_0;
        if ((Index - WSA_WAIT_EVENT_0) == 0)
        {
             WSAResetEvent(EventArray[0]);
            continue;
        }

------解决方案--------------------
0索引表示的连接事件的通知,其他的表示连接成功后,进行数据通讯的通知。