C++ – Listen for socket connections without accepting calls on Linux

Listen for socket connections without accepting calls on Linux… here is a solution to the problem.

Listen for socket connections without accepting calls on Linux

I’m running code on Ubuntu Linux and it should use Set and select to check when the listening socket has an event (i.e. someone trying to connect) and get them to connect, the problem is select ALLWAYS returns 0 when I try to connect it just connect directly.
But on the server Accept is never called because select always returns 0, so I wonder what causes this?

namespace SocketLib
{

const int MAX = FD_SETSIZE;

class SocketSet
{
public:
    SocketSet();
    void AddSocket( const Socket& p_sock );
    void RemoveSocket( const Socket& p_sock );

inline int Poll( long p_time = 0 )
    {
         this is the time value structure. It will determine how long
         the select function will wait.
        struct timeval t = { 0, p_time * 1000 };

 copy the set over into the activity set.
        m_activityset = m_set;

 now run select() on the sockets.
        #ifdef WIN32
            return select( 0, &m_activityset, 0, 0, &t );
        #else
            if( m_socketdescs.size() == 0 ) return 0;
            return select( *(m_socketdescs.rbegin()), &m_activityset, 0, 0, &t );
        #endif
    }

inline bool HasActivity( const Socket& p_sock )
    {
        return FD_ISSET( p_sock. GetSock(), &m_activityset ) != 0;
    }

protected:

 a set representing the socket descriptors.
    fd_set m_set;

 this set will represent all the sockets that have activity on them.
    fd_set m_activityset;

 this is only used for linux, since select() requires the largest
     descriptor +1 passed into it. BLAH!
    #ifndef WIN32
        std::set<sock> m_socketdescs;
    #endif
};

is the code that runs the poll in case it helps

The additional code is:

#include <algorithm>
#include "SocketSet.h"

namespace SocketLib
{

SocketSet::SocketSet()
{
    FD_ZERO( &m_set );
    FD_ZERO( &m_activityset );
}

void SocketSet::AddSocket( const Socket& p_sock )
{
     add the socket desc to the set
    FD_SET( p_sock. GetSock(), &m_set );

 if linux, then record the descriptor into the vector,
     and check if it's the largest descriptor.
    #ifndef WIN32
        m_socketdescs.insert( p_sock. GetSock() );
    #endif

}

void SocketSet::RemoveSocket( const Socket& p_sock )
{
    FD_CLR( p_sock. GetSock(), &m_set );

#ifndef WIN32
         remove the descriptor from the vector
        m_socketdescs.erase( p_sock. GetSock() );
    #endif

}

}   // end namespace SocketSet

It’s also used here
{
Define a data socket that will receive connections from listeners
socket
DataSocket data sockets;

    // detect if any sockets have action on them
    int i=m_set. Poll();
    if( i > 0 )
    {
         loop through every listening socket
        for( size_t s = 0; s < m_sockets.size(); s++ )
        {
             check to see if the current socket has a connection waiting
            if( m_set. HasActivity( m_sockets[s] ) )
            {
                try
                {
                     accept the connection
                    datasock = m_sockets[s]. Accept();

 run the action function on the new data socket
                    m_manager->NewConnection( datasock );
                    }

As you can see, it does not execute . Accept until after it gets the event from the selection, but it never that far
Bind (bind) and listen to the phone here
template
void ListeningManager::AddPort (port p_port)
{
If ( m_sockets.size() == MAX )
{
Exception e(ESocketLimitReached);
Throw (e);

    // create a new socket
    ListeningSocket lsock;

 listen on the requested port
    lsock. Listen( p_port );

 make the socket non-blocking, so that it won't block if a
     connection exploit is used when accepting (see Chapter 4)
    lsock. SetBlocking( false );

 add the socket to the socket vector
    m_sockets.push_back( lsock );

 add the socket descriptor to the set
    m_set. AddSocket( lsock );
}

Solution

select() requires a maximum fd+1. You give it maximum fd, without modification. If you see this error on Linux instead of Windows, this is the most likely cause.

Related Problems and Solutions