Windows上的Python select.select()错误10022

时间:2011-08-18 06:19:43

标签: python sockets pyqt

我得到了类(来自QThread的子类),它通过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) :
        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_()

这就是我创建套接字的方式(在其他类中):

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)

但是我每次尝试从套接字中选择时都会得到select.error 10022。我的代码出了什么问题?

3 个答案:

答案 0 :(得分:0)

你确定self.connects不是空的吗?这让我想起了在将3个空列表传递给select.select()时在Windows上出现的错误。

在任何情况下,10022都是EINVAL,意味着提供了无效参数。所以我会仔细跟踪传递给引发异常的函数的参数(看看套接字是否打开等等)

答案 1 :(得分:0)

通过临时接收代码解决:

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

答案 2 :(得分:0)

好。我很久以前就解决了这个问题。以下是使用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