如何设置QTcpServer使用Win7在端口上单独侦听

时间:2018-10-04 07:32:15

标签: qt sockets qtcpsocket qtcpserver

我使用的QTcpServer应该单独侦听端口。语言是带有Qt 5.9的c ++。该应用程序必须使用MingW在Win和Linux下运行。 QTcpServer的listen方法将标准参数用于套接字选项。对于Win10,Linux将这些选项默认设置为监听端口的单次使用,因此监听工作正常。不幸的是,Win7提供了共享用法,我必须避免这种用法。 我发现QAbstractSocket类让我使用BindFlag :: DontShareAddress创建了一个套接字。我可以将socketdescriptor转发到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;
    }
}

感谢任何想法如何设置套接字选项以专用于侦听端口。

马丁

1 个答案:

答案 0 :(得分:0)

根据评论,您可能需要在调用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,然后继续操作就会在某个时候再次咬住您。