0
votes

I'm making a simple c++ wrapper around sockets and I have a problem on windows. I initialise my server socket without any errors but when I try to connect using netcat localhost 4242 the connection is not accepted (the accept never return on the server socket).

This is the code i'm using

skt::tcp::Socket serv_socket(port_);

while (!stop_flag_)
{
    skt::tcp::Socket cli_socket;
    std::cout << "Accepting clients..." << std::endl;
    serv_socket.accept(cli_socket);
    std::cout << "New client connected : " << std::endl;
    //blabla handle the connection
}

BaseSocket.cpp

    BaseSocket::BaseSocket(int domain, int type, int protocol, const std::string &port)
{
    struct addrinfo hints;

#ifdef _WIN32
  WSADATA wsa{};

  if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
  {
    throw SocketException(std::string("Unable to initialize the socket: ") +
                          printLastError());
  }
#endif

  memset(&hints, 0, sizeof hints); // make sure the struct is empty
  hints.ai_family = domain;     // don't care IPv4 or IPv6
  hints.ai_socktype = type; 
  hints.ai_protocol = protocol;
  hints.ai_flags = AI_PASSIVE;     // fill in my IP for me

  if (getaddrinfo(NULL, port.c_str(), &hints, &servinfo_) != 0) {
      printf("getaddrinfo failed");
      //WSACleanup();
  }


  mFd = socket(servinfo_->ai_family, servinfo_->ai_socktype, servinfo_->ai_protocol);
  std::cout << "Error init socket " << WSAGetLastError() << " " << mFd << std::endl;

  if (mFd == INVALID_SOCKET)
    throw SocketException(std::string("Unable to initialize the socket: ") +
                          printLastError());
}


BaseSocket::BaseSocket(int domain, int type, int protocol)
{

#ifdef _WIN32
    WSADATA wsa{};

    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        throw SocketException(std::string("Unable to initialize the socket: ") +
            printLastError());
    }
#endif

}

void BaseSocket::bind()
{
  if (::bind(mFd, servinfo_->ai_addr, (int)servinfo_->ai_addrlen) == SOCKET_ERROR)
    throw SocketException(std::string("address binding failed: ") + printLastError());
}

void BaseSocket::listen(int backlog)
{
  if (::listen(mFd, backlog) ==  SOCKET_ERROR)
    throw SocketException(std::string("listen setting failed: ") + printLastError());
}

void BaseSocket::accept(BaseSocket &clientSocket, sockaddr *addr, socklen_t *addrlen)
{
    std::cout << "pre accept" << std::endl;
  clientSocket.mFd = ::accept(mFd, addr, addrlen);

  if (clientSocket.mFd == INVALID_SOCKET) {
      printLastError();
      std::cout << "Error onm accept " << WSAGetLastError() << std::endl;
      throw SocketException(std::string("accept failed: ") + printLastError());
  }
}

Socket.cpp

Socket::Socket(int port) :
        BaseSocket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "4242")
    {
        std::cout << "Init server socket" << std::endl;
        enableReuseAddr();
        bind();
    }

    Socket::Socket() :
        BaseSocket(SocketDomain::IP, SocketType::TCP, 0)
    {
        std::cout << "Init client socket" << std::endl;

    }

    void Socket::accept(Socket &clientSocket, int backlog)
    {
      sockaddr addr{};
      socklen_t addrlen;

      listen(backlog);
      BaseSocket::accept(clientSocket,nullptr, nullptr);

      //clientSocket.servinfo_ = addr;
    }

Any idea of what am I doing wrong here ?

1
WinSock only needs to be initialized with WSAStartup() one time, not for every socket.lorisleitner
@Loris156 Thanks, but unfortunalty that was not the source of the issue :/Théo Champion

1 Answers

1
votes

A bit late but I came accross this when I had the same problem with the time_server example in "Hands-On Network Programming with C". The question gave me the link to netcat (though I used ncat) which helped me figure it out. Using NULL as the pNodeName parameter of getaddrinfo doesn't necessarily return the localhost ip address first. Use "localhost" or "127.0.0.1". (You can use getnameinfo on the address returned by getaddrinfo to check what you are using to create the socket.)