回答给力追加分。Qt中QTcpSocket 的 connectToHost的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了回答给力追加分。Qt中QTcpSocket 的 connectToHost的问题相关的知识,希望对你有一定的参考价值。

是不是Qt环境没配置好?还是应该声明个类?看别人的connectToHost没有第三个参数啊?

文档中的说明:void QAbstractSocket::connectToHost ( const QHostAddress & address, quint16 port, OpenMode openMode = ReadWrite )
声明了QTcpSocket *tcpsocket;
写了 tcpsocket->connectToHost(&host,port);
错误:
../mysock/mainwindow.cpp: 在成员函数‘void MainWindow::on_pushButton_clicked()’中:
../mysock/mainwindow.cpp:32:40: 错误:对‘QTcpSocket::connectToHost(QString*, qint16&)’的调用没有匹配的函数
/usr/include/QtNetwork/qabstractsocket.h:128:10: 附注:备选为: void QAbstractSocket::connectToHost(const QString&, quint16, QIODevice::OpenMode)
/usr/include/QtNetwork/qabstractsocket.h:129:10: 附注: void QAbstractSocket::connectToHost(const QHostAddress&, quint16, QIODevice::OpenMode)
make: 离开目录“/home/peter/QT/mysock-build-desktop”
make: *** [mainwindow.o] 错误 1
The process "/usr/bin/make" exited with code %2.
Error while building project mysock (target: Desktop)
When executing build step 'Make'

void QAbstractSocket::connectToHost ( const QHostAddress & address, quint16 port, OpenMode openMode = ReadWrite )
第三个参数是缺省参数,可以不传递参数的,如果没有传递就按它指定的算,即ReadWrite。
另外,楼主的错误貌似和这个参数无关,而是第一个参数。第一个参数应该传的是QString的引用,而不是QString的指针。
参考技术A 你最好是检查一下你的host参数类型,是不是QString或者QHostAddress类型的,还有,你的函数调用有问题,你写的是tcpsocker->(&host, port);那么你传入的第一个参数是QString*或者是QHostAddress*类型,就是说你传入的是指针类型而不是引用类型,注意API的两个候选函数的参数是引用类型 参考技术B 第三个为默认参数,可以不填写. 参考技术C 同意前两位的说法

Qt:当用户关闭它时,在控制台应用程序中检测到 QTcpSocket 断开连接

【中文标题】Qt:当用户关闭它时,在控制台应用程序中检测到 QTcpSocket 断开连接【英文标题】:Qt: Detect a QTcpSocket disconnection in a console app when the user closes it 【发布时间】:2017-11-08 05:43:51 【问题描述】:

我的问题标题应该足够了。我已经尝试过(没有成功):

    在函数中使用 C 风格的析构函数:__attribute__((destructor)):void sendToServerAtExit() __attribute__((destructor)) mySocket->write("$%BYE_CODE%$");

调用了应用析构函数,但是socket已经断开,无法写入服务器。

    使用标准C函数atexit(),但是TCP连接已经丢失,所以我无法向服务器发送任何内容。atexit(sendToServerAtExit); // is the same function of point 1

我找到的解决方案是每秒检查所有连接的套接字是否仍然连接,但我不想这样做效率低下的事情。这只是一个临时解决方案。另外,我希望其他应用程序(甚至是网络应用程序)可以加入我的控制台应用程序的聊天室,并且我不想每秒都请求数据。

我该怎么办?

【问题讨论】:

显示你的代码。 【参考方案1】:

处理下面的信号(QTcpSocket继承自QAbstractSocket

void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)

在调用的槽内,检查socketState是否为QAbstractSocket::ClosingState

QAbstractSocket::ClosingState 表示套接字即将关闭。

http://doc.qt.io/qt-5/qabstractsocket.html#SocketState-enum

【讨论】:

或者aboutToClose() 信号在这种情况下更直接。【参考方案2】:

您可以将插槽连接到断开信号。

connect(m_socket, &QTcpSocket::disconnected, this, &Class::clientDisconnected);

检查documentation。

您还可以使用这样的插槽知道哪个用户已断开连接:

void Class::clientDisconnected

    QTcpSocket* client = qobject_cast<QTcpSocket*>(sender());
    if(client)
    
        // Do something
        client->deleteLater();
    
    else
    
        // Handle error
    

如果您有连接池,此方法很有用。如果你只有一个连接,你也可以使用它,但不要忘记nullptrclient-&gt;deleteLater() 之后。

【讨论】:

问题是关于在套接字关闭之前发送数据。 disconnected() 信号被延迟发出。 那么你应该从你的客户端实现一个预断开机制。即使是“即将断开”的 qtcpsocket 状态也是无效的,因为客户端不会监听新的传入字节。【参考方案3】:

如果我正确理解您的问题,您希望通过 TCP 发送数据以通知远程计算机您正在关闭套接字。

从技术上讲,这可以在 Qt 中通过监听 QIODevice::aboutToClose()QAbstractSocket::stateChanged() 信号来完成。

但是,如果您慷慨地退出程序并通过向远程计算机发送FIN 数据包来关闭QTcpSocket。这意味着在远程计算机上, 正在运行的程序将被通知 TCP 连接已完成。例如,如果远程程序也使用QTcpSocket,则QAbstractSocket::disconnected() 将发出信号。

真正的问题出现在其中一个程序没有正常退出时(崩溃、硬件问题、电缆拔出等)。在这种情况下,TCP FIN 数据包将 不会发送,远程计算机将永远不会收到 TCP 连接的另一端已断开连接的通知。 TCP 连接将在几分钟后超时。 但是,在这种情况下,您也无法将最终数据发送到服务器。

最后,唯一的解决方案是不时发送“我在这里”数据包。尽管您声称它效率低下,但它是一种广泛使用的技术,并且它还具有有效的优势。

【讨论】:

以上是关于回答给力追加分。Qt中QTcpSocket 的 connectToHost的问题的主要内容,如果未能解决你的问题,请参考以下文章

Qt:当用户关闭它时,在控制台应用程序中检测到 QTcpSocket 断开连接

如何安全地删除 QT::QTcpSocket?

Qt:设计QtcpSocket连接多个TcpServer?

从来自 QTcpSocket 的数据流中连续运行复杂算法的最佳 Qt 线程解决方案是啥?

QTcpSocket 读取错误

QTcpSocket使用过程中的一些问题记录