在网络编程过程中,可能需要随机的去分配网络的业务端口来满足具体的网络通信业务(RTP收发流),那么需要程序代码随机的去分配可用的端口,为了满足该种业务需求,实现如下基础的业务代码:
头文件描述基础的业务接口
#ifndef NETPORTMGR_HPP_
#define NETPORTMGR_HPP_
#define _WIN32_WINNT 0x0501
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/pool/detail/singleton.hpp>
namespace ts
{
/**
*@breif 端口管理封装
*
*/
class CNetPortMgr
{
public:
CNetPortMgr();
~CNetPortMgr();
public:
void setUp( unsigned short port = 5000 ); // 设点起始端口
void tearDown();
bool generatePort( unsigned short& port, bool bUseUDP = true );
void releasePort( unsigned short port );
bool isUseablePort( unsigned short port, bool bUseUDP = true);
private:
bool m_bSetUp; // 标志位
unsigned short m_basePort; // 起始端口
unsigned short m_nextPort; // 下一个测试端口
private:
boost::mutex m_portMutex; //支持多线程并发操作
std::list<unsigned short> m_recyclePorts; // 回收端口集合
};
typedef boost::details::pool::singleton_default<CNetPortMgr> NetPortMgrSingleton; // 单件模式
}
#endif//NETPORTMGR_H
具体的实现过程如下
#include <iostream>
#include "NetPortMgr.hpp"
namespace ts
{
CNetPortMgr::CNetPortMgr()
: m_basePort( 0 )
, m_nextPort( 0 )
, m_bSetUp( false )
{
}
CNetPortMgr::~CNetPortMgr()
{
m_recyclePorts.clear();
}
void CNetPortMgr::setUp( unsigned short port )
{
boost::mutex::scoped_lock lock( m_portMutex );
if ( m_bSetUp )
return;
m_basePort = ( port % 2 ) ? ( port + 1 ) : port;
m_nextPort = m_basePort;
m_recyclePorts.clear();
m_bSetUp = true;
}
void CNetPortMgr::tearDown()
{
boost::mutex::scoped_lock lock( m_portMutex );
m_recyclePorts.clear();
m_bSetUp = false;
}
bool CNetPortMgr::generatePort( unsigned short& port, bool bUseUDP )
{
if ( !m_bSetUp )
{
setUp();
}
boost::mutex::scoped_lock lock( m_portMutex );
///** 从已回收的端口中分配 */
while ( !m_recyclePorts.empty() )
{
unsigned short tmpPort = m_recyclePorts.front();
m_recyclePorts.pop_front();
if ( isUseablePort( tmpPort, bUseUDP ) && isUseablePort( tmpPort + 1, bUseUDP ) )
{
printf("NetPortMgr::generatePort from recycle port: %d................... \n", tmpPort);
port = tmpPort;
return true;
}
else
{
printf("NetPortMgr::generatePort from recycle error!!!!!!port: %d................... \n", tmpPort);
}
}
/** 找一个新的端口 */
while ( 1 )
{
const unsigned OVER_FLOW_MAX = 65535; // uint16_t
if ( ( (unsigned)m_nextPort + 2 ) > OVER_FLOW_MAX )
{
m_nextPort = m_basePort;
}
if ( !isUseablePort( m_nextPort ) || !isUseablePort( m_nextPort + 1 ) )
{
m_nextPort += 2;
continue;
}
else
{
port = m_nextPort;
m_nextPort += 2;
break;
}
}
return true;
}
void CNetPortMgr::releasePort( unsigned short port )
{
boost::mutex::scoped_lock lock( m_portMutex );
if ( !m_bSetUp )
return;
if ( std::find( m_recyclePorts.begin(), m_recyclePorts.end(), port ) != m_recyclePorts.end() )
return;
m_recyclePorts.push_back( port );
}
/**
*@breif 核心功能函数,通过网络方法确定端口是否被占用
*
*/
bool CNetPortMgr::isUseablePort( unsigned short port, bool bUseUDP)
{
#if defined( WIN32 ) && defined( _MSC_VER )
SOCKET sock = INVALID_SOCKET;
#elif defined( __GNUC__ )
int32_t sock = -1;
#endif
if(bUseUDP == true)
{
sock = ::socket( AF_INET, SOCK_DGRAM, 0 );
}
else
{
sock = ::socket( AF_INET, SOCK_STREAM, 0 );
}
#if defined( WIN32 ) && defined( _MSC_VER )
if ( sock == INVALID_SOCKET )
#elif defined( __GNUC__ )
if ( sock == -1 )
#endif
{
/** SOCKET错误 */
return false;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons( port );
/** 通过bind测试 */
#if defined( WIN32 ) && defined( _MSC_VER )
if ( ::bind( sock, (struct sockaddr*)&addr, sizeof(addr) ) == SOCKET_ERROR )
{
::closesocket( sock );
return false;
}
else
{
::closesocket( sock );
}
#elif defined( __GNUC__ )
if ( ::bind( sock, (struct sockaddr*)&addr, sizeof(addr) ) < 0 )
{
::close( sock );
return false;
}
else
{
::close( sock );
}
#endif
boost::thread::sleep( boost::get_system_time() + boost::posix_time::millisec( 10 ) );
return true;
}
}
如上代码可以直接使用,如有转载请支持版权