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.