为啥在 Qtcpsocket 的 readyRead 回调中调用 readAll 时没有内容?
Posted
技术标签:
【中文标题】为啥在 Qtcpsocket 的 readyRead 回调中调用 readAll 时没有内容?【英文标题】:Why is there no content when calling readAll in a Qtcpsocket's readyRead callback?为什么在 Qtcpsocket 的 readyRead 回调中调用 readAll 时没有内容? 【发布时间】:2013-07-31 11:22:57 【问题描述】:我正在构建一个最小的套接字服务器,它在收到消息时显示一个窗口。
服务器使用 newConnection 信号获取客户端连接并为每个套接字连接正确的信号(已连接、已断开和 readyRead)。
当运行服务器程序并发送一些数据到正确的地址时,对于每个发送的数据,一个 QTCPSocket 连接,然后 readyRead,然后立即断开连接。 在 readyRead 回调中, readAll 什么也不返回。 (我想这是信号断开的原因)。
仍然,客户端没有收到“断管错误”并且可以继续发送数据。
这怎么可能发生?
代码如下:
class Client(QObject):
def connects(self):
self.connect(self.socket, SIGNAL("connected()"), SLOT(self.connected()))
self.connect(self.socket, SIGNAL("disconnected()"), SLOT(self.disconnected()))
self.connect(self.socket, SIGNAL("readyRead()"), SLOT(self.readyRead()))
self.socket.error.connect(self.error)
print "Client Connected from IP %s" % self.socket.peerAddress().toString()
def error(self):
print "error somewhere"
def connected(self):
print "Client Connected Event"
def disconnected(self):
self.readyRead()
print "Client Disconnected"
def readyRead(self):
print "reading"
msg = self.socket.readAll()
print QString(msg), len(msg)
n = Notification(QString(msg))
n.show()
class Server(QObject):
def __init__(self, parent=None):
QObject.__init__(self)
self.clients = []
def setup_client_socket(self):
print "incoming"
client = Client(self)
client.socket = self.server.nextPendingConnection()
#self.client.socket.nextBlockSize = 0
client.connects()
self.clients.append(client)
def StartServer(self):
self.server = QTcpServer()
self.server.listen(QHostAddress.LocalHost, 8888)
print self.server.isListening(), self.server.serverAddress().toString(), self.server.serverPort()
self.server.newConnection.connect(self.setup_client_socket)
更新: 我直接使用 python 标准库中的 socket 模块进行了测试,它可以工作。所以我的机器和网络的一般设置不是那里的罪魁祸首。这可能是一些 QT 问题。
【问题讨论】:
在接收纯数据(控制字符、\0 等)时可能无法转换为字符串。最好将数据保留为字节数组,并在调试时使用 toHex()。 【参考方案1】:SLOT
函数需要一个表示槽名称的字符串,并且它应该在槽的目标之前:
self.connect(self.socket, SIGNAL("connected()"), self, SLOT("connected()"))
但没有引号,您正在立即调用连接线所在的函数。
由于您甚至没有使用 QtCore.Slot
/pyqtSlot
装饰器将这些函数声明为插槽,因此如果您使用 SLOT
函数,则在发出信号时无论如何都不会调用它们。
对于未修饰的 python 函数,您应该使用以下语法之一:
self.connect(self.socket, SIGNAL("connected()"), self.connected)
或者
self.socket.connected.connect(self.connected)
请注意最后一个参数末尾缺少()
。
另外你不应该在disconnected
中调用readyRead
,如果在断开之前有数据要读取,readyRead
函数很可能已经被调用了。
【讨论】:
谢谢你,我真是个笨蛋***!我想晚上编码对你来说是这样的。尽管如此,连接信号和插槽的不同方式还是有点令人费解。 pyqt 可以更明确地说明它在连接中接受的内容。【参考方案2】:可能是一个半开的套接字——你不能相信客户端总是正确地打开或终止会话。客户端可能会在没有正确挂断服务器的情况下断开连接? QTcpServer的代码我没看,可能是有人端口扫描你的盒子造成的?
无论哪种方式,服务器都应该始终能够优雅地处理不良数据或无数据。互联网是一个疯狂的地方,到处都是各种奇怪的数据包。
【讨论】:
我不确定:我直接使用标准库中的套接字模块进行了测试,它可以工作(我更新了问题以添加它)。以上是关于为啥在 Qtcpsocket 的 readyRead 回调中调用 readAll 时没有内容?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 Qtcpsocket 的 readyRead 回调中调用 readAll 时没有内容?
同一对象中的 QTcpSocket 到 QTcpSocket