I got class (subclassed from QThread), that recieve data from server at many sockets by select.select():
# -*- coding: utf-8 -*-
from PyQt4.QtCore import QThread, pyqtSignal
import json
import select
class MainSocketThread(QThread) :
disconnected_by_admin = pyqtSignal()
disconnected_by_network = pyqtSignal(bool)
def __init__(self, connects_dict=None) :
开发者_如何学Python QThread.__init__(self)
self.connects = connects_dict
if not self.connects:
self.connects={}
def run(self) :
try:
while 1 :
inputready, outputready, exceptready = select.select(self.connects.keys(),
[], [])
for s in inputready :
try :
data = self.s_[s].recv(4096)
if not data :
s.close()
self.connects.pop(s)
else :
cmd = json.loads(data)
print s, cmd, 'asd'
# ProcessCommand(s, cmd)
except Exception as e:
s.close()
self.connects.pop(s)
except Exception as e:
print e
self.disconnected_by_network.emit(False)
self.exec_()
And that's how i create socket(in other class) :
self.connections_dict = {}
self.main_socket_thread = MainSocketThread(self.connections_dict)
if not self.s :
try:
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.connect((host, port))
except Exception as e:
print e, e.__class__()
self.display_connection_status(False)
else:
self.connections_dict[self.s] = self
self.main_socket_thread.start()
self.s.send(json.dumps({'command': 'operator_insite',
'login': self.settings_dict['login'],
'password': hashlib.md5(self.settings_dict['password']).hexdigest()}))
self.display_connection_status(True)
But i got select.error 10022 every time trying to select from sockets. What is wrong with my code?
are you sure self.connects is not empty ? This reminds me of the error you get on Windows when passing 3 empty lists to select.select()
.
In any case, 10022 is EINVAL meaning an invalid argument has been supplied. So I'd carefully trace the arguments passed to the function raising the exception (seeing if the sockets are open, etc...)
Soldev by temporary recieve code:
def recv(self, sck):
data = ''
sck.settimeout(None)
data = sck.recv(1024)
sck.settimeout(0.1)
while 1:
line = ''
try:
line = sck.recv(16384)
except socket.timeout:
break
if line == '':
break
data += line
return data
Okay. I solved this problem long ago. And here is solution using Pyqt:
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)
def connectToHost(self, host, port):
self.temp = ''
self.wait_len = ''
self.abort()
QTcpSocket.connectToHost(self, host, port)
def close(self):
QTcpSocket.close(self)
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
精彩评论