简体   繁体   English

在Python asyncio中检测套接字EOF

[英]Detect socket EOF in Python asyncio

I'm writing a simple socket server that receives some messages. 我正在编写一个接收一些消息的简单套接字服务器。

The only challenge left: If the client sends EOF, the connection does not close or the EOF is detected. 唯一的挑战是:如果客户端发送EOF,则连接不会关闭或检测到EOF。

#!/usr/bin/env python

import asyncio


class Protocol(asyncio.Protocol):
    def connection_made(self, transport):
        self.peername = transport.get_extra_info("peername")
        print("Connection from %s" % (self.peername,))
        self.transport = transport

    def eof_received(self):
        print("end of stream!")
        self.close()

    def close(self):
        self.transport.close()

    def connection_lost(self, exc):
        print("Connection lost with %s" % (self.peername,))

    def data_received(self, data):
        print("received: %s" % data)


def main():
    loop = asyncio.get_event_loop()
    coro = loop.create_server(Protocol, "localhost", 1337)
    server = loop.run_until_complete(coro)

    print("Listening on %s..." % (server.sockets[0].getsockname(),))

    try:
        loop.run_forever()
    except KeyboardInterrupt:
        print("exiting...")

    server.close()
    loop.run_until_complete(server.wait_closed())
    loop.close()

if __name__ == "__main__":
    main()

I'm connecting there with strace nc localhost 1337 . 我用strace nc localhost 1337连接那里。 When I send lines to nc , they are receieved of course. 当我向nc发送线路时,他们当然会收到。 When I type Ctrl-D in nc , strace instantly reveals that socket was closed. 当我在nc键入Ctrl-D时, strace立即显示套接字已关闭。

But the python script does not notice the EOF and keeps the connection open. 但python脚本没有注意到EOF并保持连接打开。 When I kill nc , then the connection closes. 当我杀死nc ,连接关闭。

What can I do to close the connection in the asyncio protocol as soon as nc sends the EOF? 如果nc发送EOF,我该怎么做才能在asyncio协议中关闭连接?

When I type Ctrl-D in nc, strace instantly reveals that socket was closed. 当我在nc中键入Ctrl-D时,strace会立即显示套接字已关闭。

On my system w/ gnu-netcat , I have to run netcat with the -c option for the socket to be shutdown on Ctrl-D. 在我的系统w / gnu-netcat ,我必须使用-c选项运行netcat ,以便在Ctrl-D上关闭套接字。 Your script works as expected. 您的脚本按预期工作。

nc6 -x does the same thing, close the socket on eof, not just stdin . nc6 -x做同样的事情,关闭eof上的套接字,而不仅仅是stdin

It appears you have to raise an exception to end the loop. 看来你必须引发异常才能结束循环。

Here is what I have come up with: 以下是我的想法:

class Protocol(asyncio.Protocol):
    def connection_made(self, transport):
        self.peername = transport.get_extra_info("peername")
        print("Connection from %s" % (self.peername,))
        self.transport = transport

    def eof_received(self):
        print("end of stream!")

    def close(self):
        raise KeyboardInterrupt

    def connection_lost(self, exc):
        print("Connection lost with %s" % (self.peername,))
        self.close()

    def data_received(self, data):
        print("received: %s" % data)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM