为什么我的select()无法接受新客户端?

时间:2016-12-17 15:40:10

标签: c++ sockets winsock2

我正在做一个在Linux和Windows上运行的网络抽象。

要创建服务器套接字,请执行以下操作:

int TCPSocket::create(unsigned int port)
{
  _type = SERVER;
  char *ip;
  int error;

  _sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  if (_sock == INVALID_SOCKET)
  {
    std::cerr <<"Winsock error - Socket creation Failed!\n" << std::endl;
    throw std::exception();
  }

  _sockAddr.sin_family = AF_INET;
  _sockAddr.sin_port = htons(port);
  hostent* thisHost;
  thisHost = gethostbyname("");
  ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
  _sockAddr.sin_addr.s_addr = inet_addr(ip);

  error = bind(_sock, (SOCKADDR *) &_sockAddr, sizeof(SOCKADDR));
  if (error == SOCKET_ERROR)
  {
    std::cerr << "bind() failed with error:  " << WSAGetLastError() << std::endl;
    closesocket(_sock);
    WSACleanup();
    throw std::exception();
  }

  error = listen(_sock, 1);
  if (error == SOCKET_ERROR)
  {
    std::cerr << "listen() failed with error:  " << WSAGetLastError() << std::endl;
    closesocket(_sock);
    WSACleanup();
    throw std::exception();
  }
  return _sock;
}

我在TCPSocket

的向量中推送此套接字
  error = WSAStartup(MAKEWORD(2,2), &_wsaData);
  if (error)
  {
    std::cerr << "WSAStartup() failed with error:" << error << std::endl;
    throw std::exception();
  }
  TCPSocket *servSock = new TCPSocket();
  int fdCreated = servSock->create(_port);
  _fdList.push_back(servSock);

然后我用这种方式选择:

  fd_set fd_read;

  fd_set fd_write;
  int fdMax;
  int i = 0;
  int selectRet;

  FD_ZERO(&fd_read);
  FD_ZERO(&fd_write);
  fdMax = 0;
  for (ISocket *tmpSock: _fdList)
  {
    TCPSocket *socket = reinterpret_cast<TCPSocket *>(tmpSock);
    if (socket->getType() != TCPSocket::FREE)
    {
      FD_SET(socket->getSock(), &fd_read);
      FD_SET(socket->getSock(), &fd_write);
      fdMax = socket->getSock();
    }
    i++;
  }
  if ((selectRet = select(fdMax + 1, &fd_read, &fd_write, NULL, NULL)) == -1)
  {
    perror("select");
    throw std::exception();
  }
  std::cout << "good" << std::endl;
  std::cout << selectRet << std::endl;
  if (selectRet > 0)
    this->eventAction(fd_read, fd_write);

问题是,select()函数阻塞(我知道这是正常的)但是当我通过windows telnet(telnet localhost port)the select()调用将客户端连接到服务器时仍然没有返回任何东西。

这在Unix版本上运行良好。

我还注意到socket调用返回的文件描述符非常高,优于250,这是正常的吗?在Unix上,它总是返回一个低于de 5的文件描述符。

1 个答案:

答案 0 :(得分:0)

我相信您也可以将s_addr设置为零,以便将套接字绑定到所有可用地址,或者将套接字绑定到htonl(0x7f000001)上的“ 127.0.0.1”。 “ localhost”的定义可能令人惊讶。                     – D.Shawley

@ D.Shawley你是对的,我将s_addr设置为0,那行得通!                     –Dimitri Danilov