如何使用Win7设置QTcpServer单独监听端口
Posted
技术标签:
【中文标题】如何使用Win7设置QTcpServer单独监听端口【英文标题】:How set QTcpServer listening alone on port using Win7 【发布时间】:2018-10-04 07:32:14 【问题描述】:我使用应该单独侦听端口的 QTcpServer。语言是带有 Qt 5.9 的 c++。应用程序必须使用 MingW 在 Win 和 Linux 下运行。 QTcpServer 的监听方法使用标准参数作为套接字选项。对于 Win10、Linux,这些选项默认设置为监听端口的单一用途,因此监听工作正常。不幸的是,Win7 提供了我必须避免的共享使用。 我发现 QAbstractSocket 类让我可以使用 BindFlag::DontShareAddress 创建一个套接字。我可以将套接字描述符转发到 QTcpServer。然后方法监听失败(不监听),说明: 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
"The socket is assumed to be in listening state"
的文档。因此,您可以在 将套接字传递给QTcpServer::setSocketDescriptor
之前将其置于侦听状态。不确定这是否可以仅使用 Qt
来实现——您可能必须使用本机 API。
尝试设置为从 boundState 绑定后监听: bool setOk = tsocket.setSocketDescriptor(sd, QAbstractSocket::SocketState::ListeningState, QIODevice::ReadWrite);但失败了。任何其他想法如何改变套接字的状态
【参考方案1】:
根据评论,您可能需要在套接字描述符上显式调用listen
在调用QTcpServer::setSocketDescriptor
。
以下代码未经测试,但应该能给你一些想法......
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: %ld\n", WSAGetLastError());
closesocket(sd);
WSACleanup();
/*
* Handle error.
*/
if (!mServer->setSocketDescriptor(sd))
qDebug() << "SocketDescriptor fails";
顺便说一句,请注意,您需要更加小心处理错误 - 只需调用 qDebug
,然后继续会在某个时候回来咬您。
【讨论】:
感谢有关错误处理的提示 - 通过简单的调试输出,我只想大致了解情况。有没有办法只用 Qt 来解决问题(没有微软库,如上面的解决方案中所建议的那样)?以上是关于如何使用Win7设置QTcpServer单独监听端口的主要内容,如果未能解决你的问题,请参考以下文章
Qt 5.8 QTcpServer 无法监听局域网 ip 地址问题
使用 QTcpServer设置多线程客户端,解决大数据解析方案
使用 QTcpServer设置多线程客户端,解决大数据解析方案