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

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

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

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

我可以发送第一个请求并获得预期的响应。但是,当我发送第二个请求时,它似乎没有写入网络。

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

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

尝试发送后,套接字发送一个 error(RemoteHostClosedError) 信号,然后是 ClosingStateUnconnectedState 状态更改信号。

在我深入探讨之前,先问几个(可能非常基本的)问题:

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

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

这是 Mac OS X 10.8 上的最新 Qt 5.4.1,但 Windows 7.

上也会出现此问题

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

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

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)。我在任何地方都没有看到第二个请求。

最后更新:

我已经在 上发布了后续问题。

Only the second request never seems to get sent :-(

我强烈推荐 运行 像 WireShark 这样的程序,它可以查看网络上实际发送和接收的数据包。 (事实上​​,你不能确定这个bug是在客户端还是在服务器端,这是你首先要搞清楚的)

do I need to "clear" the underlying socket in any way after reading ?

没有

is it possible / probable that not reading all the data the server has sent me prevents me from writing ?

没有

why does the server close the connection ?

不看服务器的代码就说不准

Does it always do that so quickly or could that be a sign that something is not right ?

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

This worked ok. I would prefer keeping the connection open though. Is that not a reasonable approach ?

保持连接打开绝对是一个合理的方法。

What is the 'canonical' way to to implement TCP network communication ? Just read/write or re-open every time ?

两者都不是规范的;这取决于您要完成的任务。

Does the way I read from the socket have any impact on how I can write to it ?

没有

Could this possibly be a bug in the Qt event loop ?

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