对不起,是select后返回为超时

解决方案 »

  1.   

    应该是这样。
    Server端:
    WSAStartup -> socket -> bind -> listen -> WSAAsyncSelect -> accept;
    accept成功才算是真正的连通。
    Client端:
    WSAStartup -> socket -> connect -> WSAAsyncSelect;
    客户端必须调用connect请求连接。
      

  2.   

    TopLevel(),你进了一个误区,真正正确的用法是Server端:
    WSAStartup -> socket -> bind -> listen -> accept -> WSAAsyncSelect;
    Client端:
    WSAStartup -> socket -> WSAAsyncSelect -> connect;why? 很简单,避免在accept/connect 与 WSAAsyncSelect的时间间隔之内丢失FD_CONNECT/FD_ACCEPT时间!
      

  3.   

    TopLevel(),你进了一个误区,真正正确的用法是Server端:
    WSAStartup -> socket -> bind -> listen -> accept -> WSAAsyncSelect;
    Client端:
    WSAStartup -> socket -> WSAAsyncSelect -> connect;why? 很简单,避免在accept/connect 与 WSAAsyncSelect的时间间隔之内丢失FD_CONNECT/FD_ACCEPT时间!
      

  4.   

    对不起,没看很清楚Server端:
    WSAStartup -> socket -> bind -> listen -> WSAAsyncSelect -> accept;
    Client端:
    WSAStartup -> socket -> WSAAsyncSelect -> connect;
      

  5.   

    To solar,
    看看MSDN下的例子。globchat
      

  6.   

    对不起,没看很清楚Server端:
    WSAStartup -> socket -> bind -> listen -> accept -> WSAAsyncSelect;
    Client端:
    WSAStartup -> socket -> connect -> WSAAsyncSelect;
      

  7.   

    搞反了。应该是Server端:
    WSAStartup -> socket -> bind -> listen -> WSAAsyncSelect -> accept;
    Client端:
    WSAStartup -> socket -> WSAAsyncSelect -> connect;
      

  8.   

    搞反了。应该是Server端:
    WSAStartup -> socket -> bind -> listen -> WSAAsyncSelect -> accept;
    Client端:
    WSAStartup -> socket -> WSAAsyncSelect -> connect;
      

  9.   

    Server端:
    WSAStartup -> socket -> (bind) -> WSAAsyncSelect -> listen -> accept;
    Client端:
    WSAStartup -> socket -> (bind) -> WSAAsyncSelect -> connect;
      

  10.   

    〉client经过connect后总是返回连接失败WSAWOULDDBLOCK
    这是正常现象,正是异步的含义,connect成功(或失败)后会发送FD_CONNECT事件〉我不理解的疑问:server在accept时接收到的客户sockaddr的sin_port不等于客户端connect时服务器的sin_port
    客户sockaddr的sin_port与服务器的sin_port是两回事,进行TCP通讯的两端C/S每端都有一个端口,Server端的端口是通过bind绑定的,而客户端的端口则是由OS或者TCP层随机分配的
      

  11.   

    我不理解的疑问:server在accept时接收到的客户sockaddr的sin_port不等于
                   客户端connect时服务器的sin_port,我知道这都是网络字节顺序的, 
                   初始我都设为10000.为什么不相等?对于以上疑问,因为server在accept时系统自动创建一个套接字描述符,对应于几经接受的那个客户机连接,对于该客户机后续的所有操作,都应该使用这个套接字,原来的那个监听套接字,仍然用于接受其他客户机的连接,而且仍处于监听模式
      

  12.   

    wxzfox(乐乐)说的对,我一时糊涂了
      

  13.   

    > wxzfox(乐乐)说的对,我一时糊涂了
    指的是上面关于WSAAsyncSelect调用时机的问题
      

  14.   

    WSAAsyncSelect应该放在前面再去accept或connect,否则怎么触发事件!有没有别的可能?(winsock2.h和ws2_32.lib)为什么sin_port会不同?
      

  15.   

    solar(int argc,char**argv) :
    wxzfox(乐乐)说的对,我也一时胡涂了。
    我的client 非阻塞 connect时收到WSAWOULDDBLOCK属于正常情况,
    但是这么解决这个问题,select()后超时错误。
    FD_CONNECT : WSAGETSELECTERROR(lParam)错误。
      

  16.   

    因为server在accept时系统自动创建一个套接字描述符,对应于已经接受的那个客户机连接,对于该客户机后续的所有操作,都应该使用这个套接字,原来的那个监听套接字,仍然用于接受其他客户机的连接,而且仍处于监听模式。就是说ACCEPT函数得到的SOCKET是服务器在服务端建立的,与客户端的SOCKET无关,它们之间已经建立起虚电路连接,ADDRESS和PORT就可以忽略了
      

  17.   

    void main(void)
    {
       MSG msg;
       DWORD Ret;
       SOCKET Listen;
       SOCKADDR_IN InternetAddr;
       HWND Window;
       WSADATA wsaData;   if ((Window = MakeWorkerWindow()) == NULL)
          return;   // Prepare echo server   if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
       {
          printf("WSAStartup failed with error %d\n", Ret);
          return;
       }   if ((Listen = socket (PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
       {
          printf("socket() failed with error %d\n", WSAGetLastError());
          return;
       }    WSAAsyncSelect(Listen, Window, WM_SOCKET, FD_ACCEPT|FD_CLOSE);   InternetAddr.sin_family = AF_INET;
       InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
       InternetAddr.sin_port = htons(PORT);   if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
       {
          printf("bind() failed with error %d\n", WSAGetLastError());
          return;
       }   if (listen(Listen, 5))
       {
          printf("listen() failed with error %d\n", WSAGetLastError());
          return;
       }
         
       // Translate and dispatch window messages for the application thread   while(Ret = GetMessage(&msg, NULL, 0, 0))
       {
          if (Ret == -1)
          {
             printf("GetMessage() failed with error %d\n", GetLastError());
             return;
          }      TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
    }
    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);
    }
      

  18.   

    〉因为server在accept时系统自动创建一个套接字描述符,对应于已经接受的那个客户机连接,对于该客户机后续的所有操作,都应该使用这个套接字,原来的那个监听套接字,仍然用于接受其他客户机的连接,而且仍处于监听模式。就是说ACCEPT函数得到的SOCKET是服务器在服务端建立的,与客户端的SOCKET无关,它们之间已经建立起虚电路连接,ADDRESS和PORT就可以忽略了不是这样的,accept得到的sock_addr结构中的端口是客户端socket的端口,客户端socket的端口是由系统分配的;虽然accept确实创建了一个新的socket与客户端通讯,但这个新的socket的端口与listen的socket的端口是一样的(可以用getsockname看看)
      

  19.   

    wxzfox(乐乐) 我不是要例程啊,我想是阻塞和非阻塞问题。wxzfox(乐乐) 从那儿超过来的,里边有错误!
      

  20.   

    不会吧,我从《windows网络编程技术》的源代码中弄来的,应该没有问题
      

  21.   

    《windows网络编程技术》的源程序,应该没有问题