在Linux上监听套接字连接而不调用accept
我在 Ubuntu Linux 上运行代码,它应该使用 Set 和 select 来检查侦听套接字何时有活动(即有人尝试连接)并让他们连接,问题是 select ALLWAYS 返回 0,当我尝试连接时它立即连接。 但在服务器上,Accept 永远不会被调用,因为 select 总是返回 0,所以我想知道是什么导致了这种情况?
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
};
是运行民意调查的代码,以防它有帮助
附加代码是:
#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
这里也使用了它 { // 定义一个数据套接字,它将接收来自监听的连接 // 套接字 DataSocket 数据套接字;
// 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 );
}
正如你所看到的,它不会执行 .Accept 直到它从选择中获得活动之后,但它永远不会走那么远 绑定和监听调用就在这里 模板 void ListeningManager::AddPort( 端口 p_port ) { if( m_sockets.size() == MAX ) { 异常 e( ESocketLimitReached ); 抛出( 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 );
}
I am running code on Ubuntu Linux it is supposed to use a Set and select to check when a listening socket has activity (ie someone trying to connect) and let them connect, the trouble is select ALLWAYS returns 0, and when I try to connect it just connects straight away.
but on the server Accept is never called as select always returns 0, so I am wondering what could cause 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 running the poll in case it helps
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
also it is being used here
{
// define a data socket that will receive connections from the listening
// sockets
DataSocket datasock;
// 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 wont do a .Accept until AFTER it has got activity from the select, but it never gets that far
Bind and listen call is 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 );
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
select()需要最大的fd+1。你给它最大的fd,不加修改。如果您在 Linux 而不是 Windows 上看到此错误,则这是最可能的原因。
select() requires the largest fd+1. You give it the largest fd, unmodified. If you see this error on Linux and not Windows, this is the most likely cause.