我使用一个应该单独侦听端口的QTcpServer。语言是 Qt 5.9 的 c++。应用程序必须使用 MingW 在 Win 和 Linux 下运行。QTcpServer 的侦听方法使用套接字选项的标准参数。对于 Win10,Linux 这些选项默认设置为侦听端口的单一使用,因此侦听工作正常。不幸的是,与Win7提供共享用法相反,我必须避免。 我发现QAbstractSocket类允许我创建一个带有BindFlag::D ontShareAddress的套接字。我可以将套接字描述符转发到 QTcp服务器。然后,方法侦听失败(不侦听(,方法是声明:QTcpServer::listen(( 在已经侦听时调用。我使用 netstat 检查端口状态。 我的代码示例如下:
bool TcpServer::init(QString ipAddress, quint16 port, Command::RoutingProperty clientSocketKind, QString interfaceName)
{
if (mServerIsInit == true) // only 1 server instance
{
return false;
mServer = new (std::nothrow) QTcpServer();
if (mServer == nullptr)
{
return false;
}
mClientSocketKind = clientSocketKind;
mInterfaceName = interfaceName;
// tries to set socket properties to a non sharing port
QTcpSocket tsocket;
if (!tsocket.bind(QHostAddress(ipAddress), port, QAbstractSocket::BindFlag::DontShareAddress))
{
qDebug() << "Socket bind fails";
}
else
{
qDebug() << "Socket bind success";
}
sd = tsocket.socketDescriptor(); // valid socket descriptor
if (!mServer->setSocketDescriptor(sd))
{
qDebug() << "SocketDescriptor fails";
}
sd = mServer->socketDescriptor();
qDebug() << "Socketdescriptor Server " << sd;
//end tries to set socket properties to a non sharing port
if (mServer->listen(QHostAddress(ipAddress), port)) // fails with message ... is always listening
// if (mServer->mServer->isListening()) // is not listening tells netstat
{
qDebug() << "Server status for listening ok: " << mServer->isListening();
qDebug() << "Server listen on " << mServer->serverAddress() << ":" << mServer->serverPort();
connect(mServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
connect(mServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(socketErr(QAbstractSocket::SocketError)));
mServerIsInit = true;
return true;
}
else
{
qDebug() << "Server status for listening fail" << mServer->isListening();
delete mServer;
mServer = nullptr;
return false;
}
}
感谢您知道如何设置专用侦听端口的套接字选项。
马丁
根据注释,您可能需要在调用QTcpServer::setSocketDescriptor
之前在套接字描述符上显式调用listen
。
以下代码未经测试,但应该会给你一些想法......
if (!tsocket.bind(QHostAddress(ipAddress), port, QAbstractSocket::BindFlag::DontShareAddress))
{
qDebug() << "Socket bind fails";
}
else
{
qDebug() << "Socket bind success";
}
sd = tsocket.socketDescriptor(); // valid socket descriptor
/*
* Now make an explicit call to `listen' so that the socket descriptor
* can be passed to QTcpSocket::setSocketDescriptoy.
*/
if (listen(sd, SOMAXCONN) == SOCKET_ERROR)
{
printf("Listen failed with error: %ldn", WSAGetLastError());
closesocket(sd);
WSACleanup();
/*
* Handle error.
*/
}
if (!mServer->setSocketDescriptor(sd))
{
qDebug() << "SocketDescriptor fails";
}
顺便说一句,请注意,您需要更加小心错误处理 - 只需调用qDebug
,继续会在某个时候回来咬您。