python - Pyqt; QTcpSocket siempre en connectingState después del reinicio del servidor;
pyqt4 (1)
Tengo una subclase de QTcpSocket. Y el problema es: cuando llegué al servidor, todo está bien, pero después de conectar el socket reinicio el servidor (python socketServer, simplemente cierro y comienzo el script de nuevo) desconectando el socket y tratando de reconectarme mientras el servidor está inactivo, pero cuando comienzo el servidor otra vez - No pasó nada, socket.state () siempre en ConnectingState ... ¿qué pasa?
Aquí código de ejemplo:
# -*- coding: utf-8 -*-
from PyQt4.QtCore import QVariant, QTimer, pyqtSignal, QCoreApplication
import sys
from PyQt4.QtNetwork import QTcpSocket
from re import match
import json
MAX_WAIT_LEN = 8
class UpQSocket(QTcpSocket):
data_ready = pyqtSignal(unicode)
def __init__(self):
QTcpSocket.__init__(self)
self.wait_len = ''''
self.temp = ''''
self.setSocketOption(QTcpSocket.KeepAliveOption, QVariant(1))
self.readyRead.connect(self.on_ready_read)
self.connected.connect(self.on_connected)
self.disconnected.connect(self.on_disconnect)
self.error.connect(self.on_error)
self.data_ready.connect(self.print_command)
def connectToHost(self, host, port):
print ''connectToHost''
self.temp = ''''
self.wait_len = ''''
QTcpSocket.abort(self)
QTcpSocket.connectToHost(self, host, port)
def close(self):
print ''close!''
self.disconnectFromHost()
def send(self, data):
self.writeData(''%s|%s'' % (len(data), data))
def on_ready_read(self):
if self.bytesAvailable():
data = str(self.readAll())
while data:
if not self.wait_len and ''|'' in data:#new data and new message
self.wait_len , data = data.split(''|'',1)
if match(''[0-9]+'', self.wait_len) and (len(self.wait_len) <= MAX_WAIT_LEN) and data.startswith(''{''):#okay, this is normal length
self.wait_len = int(self.wait_len)
self.temp = data[:self.wait_len]
data = data[self.wait_len:]
else:#oh, it was crap
self.wait_len , self.temp = '''',''''
return
elif self.wait_len:#okay, not new message, appending
tl= int(self.wait_len)-len(self.temp)
self.temp+=data[:tl]
data=data[tl:]
elif not self.wait_len and not ''|'' in data:#crap
return
if self.wait_len and self.wait_len == len(self.temp):#okay, full message
self.data_ready.emit(self.temp)
self.wait_len , self.temp = '''',''''
if not data:
return
def print_command(self,data):
print ''data!''
def get_sstate(self):
print self.state()
def on_error(self):
print ''error'', self.errorString()
self.close()
self.connectToHost(''dev.ulab.ru'', 10000)
def on_disconnect(self):
print ''disconnected!''
def on_connected(self):
print ''connected!''
self.send(json.dumps(
{''command'' : "operator_insite",
''password'' : "376c43878878ac04e05946ec1dd7a55f",
''login'' : "nsandr",
''version'':unicode("1.2.9")}))
if __name__ == "__main__":
app = QCoreApplication(sys.argv)
main_socket = UpQSocket()
state_timer = QTimer()
state_timer.setInterval(1000)
state_timer.timeout.connect(main_socket.get_sstate)
state_timer.start()
main_socket.connectToHost(''dev.ulab.ru'', 10000)
sys.exit(app.exec_())
Aquí está la salida:
connectToHost
1
1
connected!
data!
data!
3
3
3
3
3
error The remote host closed the connection
close!
disconnected!
connectToHost
2
2
Solución:
import functools
def on_error(self):
print ''error'', self.errorString()
QTimer.singleShot(2000, functools.partial(self.connectToHost, ''localhost'', 9999))
# 2000 - your prefered reconnect timeout in ms
Actualizar
Hay más solución correcta en los comentarios para Qt bugreport QTBUG-18082 . Aquí está la implementación de Python:
@QtCore.pyqtSlot()
def do_reconnect(self):
print ''Trying to reconnect''
self.connectToHost(''localhost'', 9999)
def on_error(self):
print ''error'', self.errorString()
QtCore.QMetaObject.invokeMethod(self, ''do_reconnect'', QtCore.Qt.QueuedConnection)
o solo:
QTimer.singleShot(0, self.do_reconnect) # or any callable, slot is unnecessary
que de todos modos llamará a QtCore.QMetaObject.invokeMethod
con QueuedConnection
tipo de conexión ( fuente )