c++socketsselectstdvectorberkeley-sockets

C++ I/O Multiplexed server closes connections prematurely


i wrote a basic network programming set of C++ classes (there's nothing more than a tcp_socket a udp_socket and an ip_address wrap class class). I'm having some troubles with a I/O multiplexed server. Let me explain:

The scenario is in a way like this:

class base_socket
{
   //code for all sockets methods (both tcp and udp this class throws
   //errors and derived classes will cathc them.
   ~base_socket() { ::close(sock_fd); }
};

class udp_socket : public base_socket
{ 
  //code for the udp_socket
  virtual ~udp_socket();
};

class tcp_socket : public base_socket
{
  //code for the tcp_socket
  virtual ~tcp_socket();
};

over this scheme, depending on the application's context, I've added an ulterior level of abstraction: something like

class client_t : public tcp_socket
{
  //code for dependent client tasks
};

The main program code is something like this

int main(int argc , char *[] argv)
{
  int maxfd;
  fd_set rset;
  std::vector<base_socket> clientsV;

while(1)
{     
  FD_ZERO( &rset);

    FD_SET( {/*listening socket fd*/, &rset);

    if( clientsV.size() > 0)
        maxfd = // socket fd with max value between sockets
    else 
        maxfd = //listen socket

    for (auto it = clientsV.begin() ; it != clientsV.end(); ++it)
        FD_SET( /*client's socket fd*/, &rset);

    select( maxfd+1, &rset, NULL, NULL, NULL) < 0);

    if( FD_ISSET( /*listeing_socket*/, &rset)) 
    { 
       client_t * newclient = new client_t();
       listening_socket.accept(newclient);
       newClient->send_message("HELO");
       clientsV.push_back(*newClient);
    }


  }    
}

This works for the first client but when a second client comes it gets the HELO response but on the second clientsV.push_back(*newClient) the first connection is closed(). Any idea on what's going wrong?


Solution

  • Your clientsV member should be a std::vector<base_socket*> (i.e. keeping the pointer references). You have a chance that a temporary client_t object is being created and destroyed during push_back if it needs to relocate existing elements to a different area (See Why does vector::push_back and emplace_back call value_type::constructor twice?).

    When this happens, the ~client_t() is called and the socket is now closed.

    Also, you have a memory leak. You are allocating a pointer with new but you store the dereferenced copy. You should really just be storing the pointer as-is (and manage deleteing it when needed).