小弟最近自学Windows网络编程~~对于其中的一段代码不是很理解,求大神解答,小弟万分感激!!!!LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   SOCKET Accept;
   LPSOCKET_INFORMATION SocketInfo;
   DWORD RecvBytes, SendBytes;
   DWORD Flags;   if (uMsg == WM_SOCKET)
   {
      if (WSAGETSELECTERROR(lParam))
      {
         printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam));
         FreeSocketInformation(wParam);
      } 
      else
      {
         switch(WSAGETSELECTEVENT(lParam))
         {
            case FD_ACCEPT:               if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
               {
                  printf("accept() failed with error %d\n", WSAGetLastError());
                  break;
               }               // Create a socket information structure to associate with the
               // socket for processing I/O.               CreateSocketInformation(Accept);               printf("Socket number %d connected\n", Accept);               WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);               break;            case FD_READ:               SocketInfo = GetSocketInformation(wParam);               // Read data only if the receive buffer is empty.               if (SocketInfo->BytesRECV != 0)
               {
                  SocketInfo->RecvPosted = TRUE;
                  return 0;
               }
               else
               {
                  SocketInfo->DataBuf.buf = SocketInfo->Buffer;
                  SocketInfo->DataBuf.len = DATA_BUFSIZE;                  Flags = 0;
                  if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
                     &Flags, NULL, NULL) == SOCKET_ERROR)
                  {
                     if (WSAGetLastError() != WSAEWOULDBLOCK)
                     {
                        printf("WSARecv() failed with error %d\n", WSAGetLastError());
                        FreeSocketInformation(wParam);
                        return 0;
                     }
                  } 
                  else // No error so update the byte count
                  {
                     SocketInfo->BytesRECV = RecvBytes;
                  }
               }               // DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. Go ahead
               // and begin writing data to the client.            case FD_WRITE:                   SocketInfo = GetSocketInformation(wParam);               if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
               {
                  SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
                  SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;                  if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
                     NULL, NULL) == SOCKET_ERROR)
                  {
                     if (WSAGetLastError() != WSAEWOULDBLOCK)
                     {
                        printf("WSASend() failed with error %d\n", WSAGetLastError());
                        FreeSocketInformation(wParam);
                        return 0;
                     }
                  } 
                  else // No error so update the byte count
                  {
                     SocketInfo->BytesSEND += SendBytes;
                  }
               }               if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
               {
                  SocketInfo->BytesSEND = 0;
                  SocketInfo->BytesRECV = 0;                  // If a RECV occurred during our SENDs then we need to post an FD_READ
                  // notification on the socket.                  if (SocketInfo->RecvPosted == TRUE)
                  {
                     SocketInfo->RecvPosted = FALSE;
                     PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
                  }
               }               break;            case FD_CLOSE:               printf("Closing socket %d\n", wParam);
               FreeSocketInformation(wParam);               break;
         }
      }
      return 0;
   }   return DefWindowProc(hwnd, uMsg, wParam, lParam);
}主要是SOCKET Accept;这个是局部变量,对于收到 case FD_ACCEPT:               if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
               {
                  printf("accept() failed with error %d\n", WSAGetLastError());
                  break;
               }               // Create a socket information structure to associate with the
               // socket for processing I/O.               CreateSocketInformation(Accept);               printf("Socket number %d connected\n", Accept);               WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);               break;时候的这句 WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);不理解。这样设置非阻塞模式监听FD_READ|FD_WRITE|FD_CLOSE有用嚒?不是窗口过程执行一遍完了之后Accept套接字应该无效了嚒

解决方案 »

  1.   

    个人意见:
    我觉得这里的WSAAsyncSelect效果是不是当作SendMessage的效果呀,通知主窗体WM_SOCKET事件触发吧
      

  2.   

    是局部变量
    执行完一次,下次在Accept = accept(wParam, NULL, NULL)) 
      

  3.   

    lz 这个问题我考虑过WSAAsyncSelect这个模型, accept返回一个局部的的东东来是否需要在保存到全局中呢?我看了一个例子是没有的!!!原因不得而知。猜测是内部维护着吧!!!
      

  4.   

    有用的东西可能在CreateSocketInformation和CetSocketInformation,可惜你看都没看就来问了!另外,Accept虽然是一个临时变量,但它可能是一个系统句柄,在临时变量析构的时候,是不会释放句柄的,这就是为什么要用closesocket函数的原因。同理,HDC也是一个句柄:
    HDC hDC = GetDC();
    ...
    ReleaseDC(hDC);上面hDC是个临时变量,但如果不ReleaseDC,则会造成句柄泄漏,所以实际上,句柄是一直存在的。
      

  5.   

    SOCKET 好像是32位的一个标志,我的理解其像一个句柄,很像。socket函数创建一个套接字资源后,就会返回其句柄。码畜们使用这个句柄做其他对于WSAAsyncSelect模型, 系统内部维护着这些东西, 
    换另一个模型:select,则又全集来保存着 这些句柄,FD_CLR 翻过其代码, 所做的工作简单的把句柄拿走,应该还有其他动作,比如:清楚系统内部的东西