oo python中的套接字回调

时间:2016-04-21 06:58:17

标签: python sockets object-oriented-analysis

作为一个python newbe,我练习了几个任务,并遇到了“echo服务器”的示例代码。我将代码包装成面向对象的方式,然后偶然发现以下问题:由于示例代码使用选择器(使用回调方法)来复用io - 我可以保持面向对象的方法并将回调方法作为我班级定义的成员?

这个片段来自我的班级定义:

def accept(self, sock, mask):
    conn, addr = sock.accept()  # Should be ready
    self.log.info('New connection from ' + str(addr))
    conn.setblocking(False)
    read_wrapper = lambda x, y: self.accept(x, y)
    self.sel.register(conn, selectors.EVENT_READ, read_wrapper)

def read(self, conn, mask):
    data = conn.recv(1000)  # Should be ready
    if data:
        log.info('echoing %d bytes to %s' % (sys.getsizeof(data), conn.getpeername()))
        conn.send(data)  # Hope it won't block
    else:
        log.info('closing connection to ' + str(conn.getpeername()))
        self.sel.unregister(conn)
        conn.close()

def run(self):
    sock = socket.socket()
    sock.setblocking(False)
    sock.bind((self.server_name, self.server_port))
    sock.listen(10)
    accept_wrapper = lambda x, y: self.accept(x, y)
    self.sel.register(sock, selectors.EVENT_READ, accept_wrapper)

    self.log.info('echo server up on %s:%d' % (self.server_name, self.server_port))

    while True:
        events = self.sel.select()
        for key, mask in events:
            callback = key.data
            callback(key.fileobj, mask)

我试图用lambda(read_wrapper和accept_wrapper)解决这个问题而没有运气 - 因为我得到了这个Traceback:

Traceback (most recent call last):
  File "echo.py", line 141, in <module>
    app.run()
  File "echo.py", line 127, in run
    callback(key.fileobj, mask)
  File "echo.py", line 100, in <lambda>
    read_wrapper = lambda x, y: self.accept(x, y)
  File "echo.py", line 97, in accept
    conn, addr = sock.accept()  # Should be ready
  File "/usr/lib/python3.4/socket.py", line 187, in accept
    fd, addr = self._accept()
OSError: [Errno 22] Invalid argument

1 个答案:

答案 0 :(得分:0)

不知道它是最好的解决方案还是解决方案,但它适用于闭包

def run(self):
    sock = socket.socket()
    sock.setblocking(False)
    sock.bind((self.server_name, self.server_port))
    sock.listen(10)

    def read(conn, mask):
        data = conn.recv(1000)  # Should be ready
        if data:
            self.log.info('echoing %d bytes to %s' % (sys.getsizeof(data), conn.getpeername()))
            conn.send(data)  # Hope it won't block
        else:
            self.log.info('closing connection to ' + str(conn.getpeername()))
            self.sel.unregister(conn)
            conn.close()

    def accept(sock, mask):
        conn, addr = sock.accept()  # Should be ready
        self.log.info('New connection from ' + str(addr))
        conn.setblocking(False)
        self.sel.register(conn, selectors.EVENT_READ, read)

    self.sel.register(sock, selectors.EVENT_READ, accept)

    self.log.info('echo server up on %s:%d' % (self.server_name, self.server_port))

    while True:
        events = self.sel.select()
        for key, mask in events:
            callback = key.data
            callback(key.fileobj, mask)