C++/Qt:QTcpSocket 读取后不会写入

C++/Qt: QTcpSocket won't write after reading

本文关键字:读取 Qt QTcpSocket C++      更新时间:2023-10-16

我正在创建一个网络客户端应用程序,该应用程序使用QTcpSocket向服务器发送请求,并期望得到响应。不涉及更高的协议(HTTP等),它们只是交换一些简单的自定义字符串。

为了进行测试,我用Python创建了一个TCP服务器,它监听套接字并记录它接收到的字符串和发回的字符串。

我可以发送第一个请求OK并得到预期的响应。然而,当我发送第二个请求时,它似乎没有被写入网络。

我在QTcpSocket的通知信号上附加了调试槽,如bytesWritten(...)connected()error()stateChanged(...)等。我看到了正在建立的连接、发送的第一个请求、处理的第一个响应、写入的字节数——所有这些加起来。。。

只有第二个请求似乎从未被发送:-(

在尝试发送它之后,套接字发送error(RemoteHostClosedError)信号,然后是ClosingStateUnconnectedState状态改变信号。

在我深入研究之前,有几个(可能真的很基本)问题:

  1. 阅读后,我是否需要以任何方式"清除"底层套接字
  2. 有没有可能因为没有读取服务器发送给我的所有数据而阻止我写作
  3. 服务器为什么关闭连接?它总是这么快做到这一点,还是这可能是某件事不对劲的迹象?我尝试设置LowDelayKeepAlive套接字选项,但这并没有改变任何内容。我还检查了套接字的state()isValid(),它们都很好——尽管后者在未连接时也会返回true
  4. 在应用程序的早期版本中,我在发送请求之前关闭并重新打开了连接。这还可以。不过我更希望保持连接打开。这不是一个合理的做法吗?实现TCP网络通信的"规范"方法是什么?每次都只是读/写还是重新打开
  5. 我从套接字中读取的方式对我如何向其写入有任何影响吗?大多数示例代码使用readAll(...)来获取所有可用数据;我根据需要一篇一篇地阅读,并在写作时将<<转换为QTextStream

这可能是Qt事件循环中的一个错误吗?我观察到,使用QDebug() << ...创建的Qt Creator控制台中的输出几乎总是被缩短,即停止。有时,当我关闭应用程序时,会打印更多的输出。

这是Mac OS X 10.8上最新的Qt 5.4.1,但该问题也发生在Windows 7上。

第一次回答和评论后更新:

测试服务器非常简单,取自官方Python SocketServer.TCPServer示例:

import SocketServer
class MyTCPHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        request  = self.rfile.readline().strip()
        print "RX [%s]: %s" % (self.client_address[0], request)
        response = self.processRequest(request)
        print "TX [%s]: %s" % (self.client_address[0], response)
        self.wfile.write(response)
    def processRequest(self, message):
        if   message == 'request type 01':
            return 'response type 01'
        elif message == 'request type 02':
            return 'response type 02'
if __name__ == "__main__":
    server = SocketServer.TCPServer(('localhost', 12345), MyTCPHandler)
    server.serve_forever()

我得到的输出是

RX [127.0.0.1]: request type 01
TX [127.0.0.1]: response type 01

此外,当我在这之后重新发送任何消息时,都不会发生任何事情——这并不奇怪,因为套接字是关闭的。我想我必须弄清楚为什么它关闭了。。。

下一次更新:

我已经使用Wireshark捕获了网络流量,虽然所有的网络内容并没有告诉我很多,但我确实看到了第一个请求和响应。在客户端[ACK]确认响应之后,服务器立即发送Connection finish (FIN)。我在任何地方都看不到第二个请求。

上次更新:

我在Python上发布了一个后续问题:SocketServer意外关闭TCP连接。

只有第二个请求似乎从未被发送:-(

我强烈建议运行WireShark这样的程序,看看网络上实际发送和接收的数据包是什么。(事实上,你不能确定错误是在客户端还是在服务器上,这是你需要弄清楚的第一件事)

阅读后,我是否需要以任何方式"清除"底层套接字?

没有。

是否可能没有读取服务器的所有数据发送给我阻止我写作?

没有。

服务器为什么关闭连接?

如果不看服务器的代码,就不可能说出来。

它总是这么快做到这一点吗?或者这可能是一个迹象有什么不对吗?

同样,这将取决于服务器的编写方式。

这还可以。不过我更希望保持连接打开。是这不是一个合理的方法吗?

保持连接开放无疑是一种合理的方法。

实现TCP网络通信的"规范"方法是什么?每次都只是读/写还是重新打开?

两者都不是规范的;这取决于你想要完成什么。

我从套接字中读取的方式对我的写作方式有影响吗对它?

没有。

这可能是Qt事件循环中的一个错误吗?

这是极不可能的。Qt代码已经被成千上万的程序使用了多年,所以任何严重的错误几乎肯定早就被发现并修复了。更有可能的是,您的客户端或服务器中存在错误,或者您期望某些API调用的行为方式与其实际行为方式不匹配。