监听同一端口通常会报错误,端口已经被绑定。但是有需求使用同一个端口对外网开放,同一进程只链接一个客户端,因此有了这个想法。将所有进程启动初始化,然后在监听前使用记录锁,保证获取到锁的进程才能启动监听。当客户端链接后释放记录锁,使其它进程可以获取该记录锁。因此,达到多进程监听同一端口的需求。
监听前:
int opt=1;
setsockopt(m_server->socketDescriptor(), SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
waitForStartNet();
return m_server->listen(QHostAddress(host), port);
waitForStartNet实现为记录锁:
QString locker = iMAGESUtils::getProcPath() + LISTEN_FLAG;
QFile *fLocker = new QFile(locker);
if(!fLocker->open(QFile::ReadWrite))
{
return;
}
int lockfd = fLocker->handle();
gHandlesMap[LISTEN_FLAG] = lockfd;
if( -1 == flock(lockfd, LOCK_EX) )
{
return;
}
当接到新连接时关闭监听,同时释放句柄,释放记录锁:
m_socket = m_server->nextPendingConnection();
m_server->close();
releaseStartNet();
close(m_server->socketDescriptor());
connect(m_socket, SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(onBinaryMessageReceived(QByteArray)));
connect(m_socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
releaseStartNet释放记录锁的实现为:
if(!gHandlesMap.contains(LISTEN_FLAG))
{
return true;
}
int lockfd = gHandlesMap[LISTEN_FLAG];
if( -1 == flock(lockfd, LOCK_UN) )
{
return false;
}
return true;
备注:该方案仅在linux系统下可用。
网友评论