简体   繁体   English

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

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

I am creating a network client application that sends requests to a server using a QTcpSocket and expects responses in return. 我正在创建一个网络客户端应用程序,它使用QTcpSocket将请求发送到服务器,并期望得到响应。 No higher protocol involved (HTTP, etc.), they just exchange somewhat simple custom strings. 没有更高的协议(HTTP等),他们只是交换一些简单的自定义字符串。

In order to test, I have created a TCP server in Python that listens on a socket and logs the strings it receives and those it sends back. 为了测试,我在Python中创建了一个TCP服务器,它监听套接字并记录它接收的字符串和它发回的字符串。

I can send the first request OK and get the expected response. 我可以发送第一个请求OK并获得预期的响应。 However, when I send the second request, it does not seem to get written to the network. 但是,当我发送第二个请求时,似乎没有写入网络。

I have attached debug slots to the QTcpSocket 's notification signals, such as bytesWritten(...) , connected() , error() , stateChanged(...) , etc. and I see the connection being established, the first request sent, the first response processed, the number of bytes written - it all adds up... 我已经将调试槽附加到QTcpSocket的通知信号,例如bytesWritten(...)connected()error()stateChanged(...)等等,我看到连接正在建立,第一个请求发送,第一个响应处理,写入的字节数 - 这一切加起来......

Only the second request never seems to get sent :-( 只有第二个请求似乎永远不会被发送:-(

After attempting to send it, the socket sends an error(RemoteHostClosedError) signal followed by ClosingState and UnconnectedState state change signals. 尝试发送之后,插座发送一个error(RemoteHostClosedError)随后信号ClosingStateUnconnectedState状态变化的信号。

Before I go any deeper into this, a couple of (probably really basic) questions: 在我深入研究这个问题之前,有几个(可能是非常基本的)问题:

  1. do I need to "clear" the underlying socket in any way after reading ? 读完后我需要以任何方式“清除”底层套接字吗?
  2. is it possible / probable that not reading all the data the server has sent me prevents me from writing ? 是否有可能/可能不读取服务器发送给我的所有数据会阻止我写作?
  3. 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 ? 它总是如此迅速地做到这一点,还是表明事情不对? I tried setting LowDelay and KeepAlive socket options, but that didn't change anything. 我尝试设置LowDelayKeepAlive套接字选项,但这并没有改变任何东西。 I've also checked the socket's state() and isValid() and they're good - although the latter also returns true when unconnected... 我还检查了socket的state()isValid()并且它们很好 - 虽然后者在未连接时也返回true ...
  4. In an earlier version of the application, I closed and re-opened the connection before sending a request. 在该应用程序的早期版本中,我在发送请求之前关闭并重新打开了连接。 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 ? 实施TCP网络通信的“规范”方法是什么? Just read/write or re-open every time ? 只是每次读/写或重新打开?
  5. Does the way I read from the socket have any impact on how I can write to it ? 我从套接字读取的方式对我如何写入它有什么影响吗? Most sample code uses readAll(...) to get all available data; 大多数示例代码使用readAll(...)来获取所有可用数据; I read piece by piece as I need it and << to a QTextStream when writing... 我读了一块一块的,因为我需要它, <<QTextStream写作时...

Could this possibly be a bug in the Qt event loop ? 这可能是Qt事件循环中的错误吗? I have observed that the output in the Qt Creator console created with QDebug() << ... almost always gets cut short, ie just stops. 我观察到用QDebug() << ...创建的Qt Creator控制台中的输出几乎总是被缩短,即停止。 Sometimes some more output is printed when I shut down the application. 当我关闭应用程序时,有时会打印更多输出。

This is with the latest Qt 5.4.1 on Mac OS X 10.8, but the issue also occurs on Windows 7. 这是在Mac OS X 10.8上的最新Qt 5.4.1,但问题也发生在Windows 7上。

Update after the first answer and comments: 第一个答案和评论后更新:

The test server is dead simple and was taken from the official Python SocketServer.TCPServer Example : 测试服务器很简单,取自官方的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()

The output I get is 我得到的输出是

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

Also, nothing happens when I re-send any message after this - which is not surprising as the socket was closed. 此外,在此之后重新发送任何消息时没有任何反应 - 这在插座关闭时并不奇怪。 Guess I'll have to figure out why it is closed... 猜猜我得弄明白为什么关闭......

Next update: 下次更新:

I've captured the network traffic using Wireshark and while all the network stuff doesn't really tell me a lot, I do see the first request and the response. 我使用Wireshark捕获了网络流量,虽然所有的网络内容并没有真正告诉我很多,但我确实看到了第一个请求和响应。 Right after the client [ACK] nowledges the response, the server sends a Connection finish (FIN) . 在客户端[ACK]现在响应后,服务器发送Connection finish (FIN) I don't see the second request anywhere. 我没有在任何地方看到第二个请求。

Last update: 最后更新:

I have posted a follow-up question at Python: SocketServer closes TCP connection unexpectedly . 我在Python上发布了一个后续问题:SocketServer意外关闭了TCP连接

Only the second request never seems to get sent :-( 只有第二个请求似乎永远不会被发送:-(

I highly recommend running a program like WireShark and seeing what packets are actually getting sent and received across the network. 我强烈建议运行像WireShark这样的程序,看看实际上通过网络发送和接收的数据包。 (As it is, you can't know for sure whether the bug is on the client side or in the server, and that is the first thing you need to figure out) (实际上,您无法确定该错误是在客户端还是在服务器中,这是您需要弄清楚的第一件事)

do I need to "clear" the underlying socket in any way after reading ? 读完后我需要以任何方式“清除”底层套接字吗?

No. 没有。

is it possible / probable that not reading all the data the server has sent me prevents me from writing ? 是否有可能/可能不读取服务器发送给我的所有数据会阻止我写作?

No. 没有。

why does the server close the connection ? 为什么服务器关闭连接?

It's impossible to say without looking at the server's code. 没有看服务器的代码就不可能说。

Does it always do that so quickly or could that be a sign that something is not right ? 它总是如此迅速地做到这一点,还是表明事情不对?

Again, this would depend on how the server was written. 同样,这将取决于服务器的编写方式。

This worked ok. 这工作正常。 I would prefer keeping the connection open though. 我宁愿保持连接打开。 Is that not a reasonable approach ? 这不是一个合理的方法吗?

Keeping the connection open is definitely a reasonable approach. 保持连接打开绝对是一种合理的方法。

What is the 'canonical' way to to implement TCP network communication ? 实施TCP网络通信的“规范”方法是什么? Just read/write or re-open every time ? 只是每次读/写或重新打开?

Neither was is canonical; 这两者都不是规范的; it depends on what you are attempting to accomplish. 这取决于你想要完成的事情。

Does the way I read from the socket have any impact on how I can write to it ? 我从套接字读取的方式对我如何写入它有什么影响吗?

No. 没有。

Could this possibly be a bug in the Qt event loop ? 这可能是Qt事件循环中的错误吗?

That's extremely unlikely. 那是极不可能的。 The Qt code has been used for years by tens of thousands of programs, so any bug that serious would almost certainly have been found and fixed long ago. Qt代码已被成千上万的程序使用多年,因此任何严重的错误几乎肯定会在很久以前找到并修复。 It's much more likely that either there is a bug in your client, or a bug in your server, or a mismatch between how you expect some API call to behave and how it actually behaves. 您的客户端中存在错误或服务器中存在错误,或者您希望某些API调用的行为方式与实际行为之间存在不匹配的可能性更大。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM