windows网络编程中有一段代码,是关于Overlap Socket IO models的在main函数的最后,有这一段代码
if (WSASetEvent(EventArray[0]) == FALSE)
     {
        printf("WSASetEvent failed with error %d\n", WSAGetLastError());
         return;
     }
   }}在线程ProcessIO(LPVOID lpParameter)中有下列一段代码
{
   DWORD Index;
   DWORD Flags;
   LPSOCKET_INFORMATION SI;
   DWORD BytesTransferred;
   DWORD i;
   DWORD RecvBytes, SendBytes;   // Process asynchronous WSASend, WSARecv requests.   while(TRUE)
   {      if ((Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE,
         WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED)
      {
         printf("WSAWaitForMultipleEvents failed %d\n", WSAGetLastError());
         return 0;
      }       // If the event triggered was zero then a connection attempt was made
      // on our listening socket.
 
      if ((Index - WSA_WAIT_EVENT_0) == 0)
      {
         WSAResetEvent(EventArray[0]);
         continue;
      }请问为什么在main中要设置EventArray[0]的hEvent为Signaled状态呢?
ProcessIO中除了WSAResetEvent(...)之外,什么都没做啊?下面这个地址同样的问题给了50分,谢谢指教
http://www.csdn.net/expert/topic/855/855868.xml?temp=.5517084

解决方案 »

  1.   

    你没有看到前面的
    if ((Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE,
             WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED)这里面就用到了EventArray[0]了。
      

  2.   

    没看过那本书,不知道全部。
    根据经验main()的结尾中WSAResetEvent(hEvent)
    是希望某一线程自觉结束,那个线程以hEvent为等待结束条件。但是,ProcessIO()显然不是main要赐死线程。因为      if ((Index - WSA_WAIT_EVENT_0) == 0)
          {
             WSAResetEvent(EventArray[0]);
             continue;
          }
    那个线程应该在书的其他地方。
    也许是瞎猜!!!!!!!!!!!!!!!!!!
      

  3.   

    我把全部代码贴出来吧,请大家费心看看,一定给分// Module Name: overlap.cpp
    //
    // Description:
    //
    //    This sample illustrates how to develop a simple echo server Winsock
    //    application using the Overlapped I/O model with event notification. This 
    //    sample is implemented as a console-style application and simply prints
    //    messages when connections are established and removed from the server.
    //    The application listens for TCP connections on port 5150 and accepts them
    //    as they arrive. When this application receives data from a client, it
    //    simply echos (this is why we call it an echo server) the data back in
    //    it's original form until the client closes the connection.
    //
    // Compile:
    //
    //    cl -o overlap overlap.cpp ws2_32.lib
    //
    // Command Line Options:
    //
    //    overlap.exe 
    //
    //    Note: There are no command line options for this sample.#include <winsock2.h>
    #include <windows.h>
    #include <stdio.h>#define PORT 5150
    #define DATA_BUFSIZE 8192typedef 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;   void main(void)
    {
       WSADATA wsaData;
       SOCKET ListenSocket, AcceptSocket;
       SOCKADDR_IN InternetAddr;
       DWORD Flags;
       DWORD ThreadId;
       DWORD RecvBytes;
       INT Ret;   InitializeCriticalSection(&CriticalSection);   if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
       {
          printf("WSAStartup failed with error %d\n", Ret);
          WSACleanup();
          return;
       }   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;
       }   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;
       }   if (listen(ListenSocket, 5))
       {
          printf("listen() failed with error %d\n", WSAGetLastError());
          return;
       }   // 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;
       }   if ((EventArray[0] = WSACreateEvent()) == WSA_INVALID_EVENT)
       {
          printf("WSACreateEvent failed with error %d\n", WSAGetLastError());
          return;
       }   // 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;
       }    EventTotal = 1;   while(TRUE)
       {
           // Accept inbound connections      if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) == INVALID_SOCKET)
          {
              printf("accept failed with error %d\n", WSAGetLastError());
              return;
          }      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;
          }       // 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;
          }      // 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;
             }
          }      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;
          }
       }}
      

  4.   

    DWORD WINAPI ProcessIO(LPVOID lpParameter)
    {
       DWORD Index;
       DWORD Flags;
       LPSOCKET_INFORMATION SI;
       DWORD BytesTransferred;
       DWORD i;
       DWORD RecvBytes, SendBytes;   // Process asynchronous WSASend, WSARecv requests.   while(TRUE)
       {      if ((Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE,
             WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED)
          {
             printf("WSAWaitForMultipleEvents failed %d\n", WSAGetLastError());
             return 0;
          }       // If the event triggered was zero then a connection attempt was made
          // on our listening socket.
     
          if ((Index - WSA_WAIT_EVENT_0) == 0)
          {
             WSAResetEvent(EventArray[0]);
             continue;
          }      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());
             }         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 gauranteed 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
          {
             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;
                }
             }
          }
       }
    }
      

  5.   

    一句话,为什么要WSASetEvent(EventArray[0])
    谢谢大家了
      

  6.   

    我来帮你一把
    WSASetEvent函数的作用是:
        The WSASetEvent function sets the state of the event object to be signaled.
        就是设置事件有信号。
        
    WSAWaitForMultipleEvents函数的作用是:
        The WSAWaitForMultipleEvents function returns when any one or all of the specified 
    objects are in the signaled state, or when the time-out interval elapses. This 
    function is also used to perform an alertable wait by setting the parameter fAltertable
    to be TRUE. This enables the function to return when the system queues an I/O completion 
    routine to be executed by the calling thread.
        就是等待一组事件那个有信号,返回的值是WSA_WAIT_EVENT_0+有信号的事件在数组中位置。WSAResetEvent函数的作用是:
    The Windows Sockets WSAResetEvent function resets the state of the specified event object 
    to nonsignaled.
        就是设置一事件没有信号。具体函数参数要求,请见MSDN
      

  7.   

    噢,我想我明白了,這段程式的作者是想用一個不會自動變為有信號的Event(EventArray[0])來使子線程ProcessIO啟動后當在WSAWaitForMultipleEvents那一句的地方,然后當有一個客戶端連進來後就用WSASetEvent手動去觸發WSAWaitForMultipleEvents返回,並再設定EventArray[0]為無信號的留作等待下一個連接時使用.這樣可以節省系統開銷吧!