如何使用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单独监听端口的主要内容,如果未能解决你的问题,请参考以下文章

QTcpServer服务器无法监听和客户端连接不上问题

Qt 5.8 QTcpServer 无法监听局域网 ip 地址问题

使用 QTcpServer设置多线程客户端,解决大数据解析方案

使用 QTcpServer设置多线程客户端,解决大数据解析方案

使用 QTcpServer设置多线程客户端,解决大数据解析方案

如何在 QTcpServer 使用的套接字上设置 SO_REUSEADDR?