更多
恢复
2019年02月12日 11点07分 留白

我写了一个socket服务器,使用了协程进行驱动,可以进行连接但是出现了bug,启动之后如果使用谷歌浏览器进行访问如果一段时间不刷新或者不用新的页面访问就会报错

Traceback (most recent call last):
  File "E:/git/web-socket/DAWN/IOloop.py", line 126, in <module>
    event.run_forever()
  File "E:/git/web-socket/DAWN/IOloop.py", line 49, in run_forever
    events = self.selector.select()
  File "C:\Users\lenovo\Desktop\work\python3\Python\Python36\lib\selectors.py", line 323, in select
    r, w, _ = self._select(self._readers, self._writers, [], timeout)
  File "C:\Users\lenovo\Desktop\work\python3\Python\Python36\lib\selectors.py", line 314, in _select
    r, w, x = select.select(r, w, w, timeout)
OSError: [WinError 10038] 在一个非套接字上尝试了一个操作。



但是我写了一个client访问服务器绑定的端口的时候就不会出现这种bug,我是在Python3.6的版本,win10 pycharm上运行的

下面是我的代码


import socket
import selectors


class Future():
    def __init__(self):
        self.result = None
        self._callback = []

    def add_done_callback(self, fn):
        self._callback.append(fn)

    def set_result(self, result):
        self.result = result
        for callback in self._callback:
            callback()

    def __iter__(self):
        yield self
        return self.result

class Task():
    def __init__(self, coro):
        self.coro = coro
        # f = Future()
        # f.set_result(None)
        self.step()

    def step(self):
        try:
            next_future = self.coro.send(None)
        except StopIteration:
            return
        if len(next_future._callback) <= 0:
            next_future.add_done_callback(self.step)


class IOLoop():
    def __init__(self, selector=None):
        if selector is None:
            selector = selectors.DefaultSelector()
        self.selector = selector

    def create_task(self, coro):
        return Task(coro)

    def run_forever(self):
        while True:
            events = self.selector.select()
            for key, mask in events:
                callback = key.data
                callback()


class TCPServer():
    def __init__(self, host, port, loop):
        self.host = host
        self.port = port
        self._loop = loop
        self.sock = socket.socket()

    def run(self):
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind((self.host, self.port))
        self.sock.listen(128)
        self.sock.setblocking(False)

        while 1:
            conn, addr = yield from self._accept()
            print('conn ', conn, 'addr ', addr)
            data = yield from self._read(conn)
            print('data', data)
            if data:
                yield from self.sendall(conn, data)
            else:
                conn.close()

    def _accept(self):
        f = Future()

        def on_accept():
            conn, addr = self.sock.accept()
            print('accepted', conn, 'from', addr)
            conn.setblocking(False)
            f.set_result((conn, addr))
        self._loop.selector.register(self.sock, selectors.EVENT_READ, on_accept)
        conn, addr = yield from f
        self._loop.selector.unregister(self.sock)
        return conn, addr

    def _read(self, conn):
        f = Future()

        def read():
            data = b''
            while True:
                sock_data = conn.recv(1024)
                data += sock_data
                if len(sock_data) < 1024:
                    break
            f.set_result((data))
        self._loop.selector.register(conn, selectors.EVENT_READ, read)
        data = yield from f
        return data

    def sendall(self, conn, data):
        f = Future()

        def write():
            conn.sendall(data)
            conn.close()
            print('closing', conn)
            f.set_result(None)
        self._loop.selector.modify(conn, selectors.EVENT_WRITE, write)
        yield from f
        self._loop.selector.unregister(conn)


event = IOLoop()
TCP = TCPServer('localhost', 2000, event)
task = Task(TCP.run())
event.run_forever()

修改

Python 编程开发语言 修改

应答 (下拉快捷留言)

知道“一起帮”的协助流程么?不要搞错哟:应答握手再远程……

(´・・)ノ(._.`)
还没有内容呢!等待求助被解决(酬谢/撤销)后,求助人或好心人总结……

关键字



帮助

反馈