Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 异步客户端:`connection_lost`未调用,导致ResourceWarning_Python_Sockets_Python Asyncio - Fatal编程技术网

Python 异步客户端:`connection_lost`未调用,导致ResourceWarning

Python 异步客户端:`connection_lost`未调用,导致ResourceWarning,python,sockets,python-asyncio,Python,Sockets,Python Asyncio,我使用asyncio客户端连接服务器,然后断开与服务器的连接 如果我连接到同一台计算机上的服务器程序,连接将正常关闭添加:当我开始向连接写入数据时,此连接有时也会发出警告。请参阅下面的第二个代码版本 如果我连接到本地网络上的设备,我将获得未关闭传输的ResourceWarning 如何正确关闭连接? 我在Windows7(64位)上使用Python 3.6.0(32位) 第一次尝试 相关代码: import asyncio import logging import warnings cl

我使用asyncio客户端连接服务器,然后断开与服务器的连接

  • 如果我连接到同一台计算机上的服务器程序,连接将正常关闭添加:当我开始向连接写入数据时,此连接有时也会发出警告。请参阅下面的第二个代码版本

  • 如果我连接到本地网络上的设备,我将获得未关闭传输的
    ResourceWarning

如何正确关闭连接?

我在Windows7(64位)上使用Python 3.6.0(32位)

第一次尝试 相关代码:

import asyncio
import logging
import warnings

class ClientConnection(asyncio.Protocol):
    def connection_made(self, transport):
        self.transport = transport
        transport.write_eof()  # Send EOF to close connection

    def connection_lost(self, exception):
        self.transport.close()
        super().connection_lost(exception)

def main():
    logging.basicConfig(level=logging.DEBUG)
    eventLoop = asyncio.get_event_loop()
    eventLoop.set_debug(True)
    warnings.simplefilter('always', ResourceWarning)  # enables ResourceWarning
    #co = eventLoop.create_connection(ClientConnection, '127.0.0.1', 7001)     # Works without warning
    co = eventLoop.create_connection(ClientConnection, '192.168.10.66', 7001)  # Gives warning
    try:
        eventLoop.run_until_complete(co)
    finally:
        eventLoop.close()

if __name__ == "__main__":
    main()
控制台输出:

DEBUG:asyncio:Using selector: SelectSelector
DEBUG:asyncio:connect <socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6> to ('19
2.168.10.66', 7001)
DEBUG:asyncio:poll took 0.000 ms: 1 events
DEBUG:asyncio:<socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168
.10.62', 64587), raddr=('192.168.10.66', 7001)> connected to 192.168.10.66:7001: (<_SelectorSocketTransport fd=240 read=
polling write=<idle, bufsize=0>>, <__main__.ClientConnection object at 0x005EBD90>)
DEBUG:asyncio:Close <_WindowsSelectorEventLoop running=False closed=False debug=True>
sys:1: ResourceWarning: unclosed <socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto
=6, laddr=('192.168.10.62', 64587), raddr=('192.168.10.66', 7001)>
C:\Program Files (x86)\Python36-32\lib\asyncio\selector_events.py:631: ResourceWarning: unclosed transport <_SelectorSoc
ketTransport fd=240>
  source=self)
成功时输出:

...
DEBUG:root:EOF received
DEBUG:root:connection_lost
DEBUG:root:done
DEBUG:asyncio:Close <_WindowsSelectorEventLoop running=False closed=False debug=True>

等待服务器关闭连接,或者使用
transport.close()
关闭传输。这也将触发
连接丢失
(不要调用
传输关闭()
连接丢失
!):


如果您再尝试一点,您可能也会得到一些本地机器的
ResourceWarning
s。例如,尝试在
write\u eof()
之前添加
transport.write(b'hello world!')
,或者使本地服务器响应较慢。

尝试运行更多的循环。下面是一个使用
loop.run_forever()
loop.stop()
的示例,假设在本地和远程计算机上有:

import asyncio
import logging

import warnings


class ClientConnection(asyncio.Protocol):
    def connection_made(self, transport):
        logging.debug("connection made, sending and calling write eof")
        transport.write(b'hello')
        transport.write_eof()
        logging.debug("after calling write eof")

    def data_received(self, data):
        logging.debug("Got: {}".format(data))
        super().data_received(data)

    def connection_lost(self, exception):
        logging.debug("connection lost")
        super().connection_lost(exception)
        loop.stop()


def test_echo(ip, port):
    logging.debug("Creating connection: {}:{}".format(ip, port))
    co = loop.create_connection(ClientConnection, ip, port)
    logging.debug("Starting loop...")
    print(loop.run_until_complete(co))
    logging.debug("...create_connection done, running loop forever...")
    loop.run_forever()
    logging.debug("Loop stopped")

    logging.debug('----------------')


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    warnings.simplefilter('always')  # enables ResourceWarning

    loop = asyncio.get_event_loop()
    loop.set_debug(True)

    test_echo('127.0.0.1', 7001)
    test_echo('54.175.103.105', 30000)

    logging.debug("done")
    loop.close()

关于将数据发送到localhost套接字,您是对的:它也会触发警告。但是我也无法从
连接关闭传输,我开始收到操作错误。我已经修改了这个问题。张贴这是一个新的问题,可能会使更多的SeaSoError可能需要去另一个问题(我会编辑排除它),但是这个问题仍然是开放的:有时,代码>连接连接丢失>代码不被调用,这给了警告。无法在linux:-)上复制
WinError
)传输。关闭()可以正常工作。尝试在
.close()之前添加
time.sleep(0.05)
@Udi Timeout似乎没有帮助,Windows似乎对某些事情很挑剔。我可能会问另一个问题。但是,单独使用延迟似乎可以防止最初的问题。我需要做一些测试,但可能是我的程序做任何事情都太快了。感谢您迄今为止的帮助。显然在windows下
write\eof
调用
close()
。另外:尝试永远运行循环,并在连接丢失时停止它。
...
DEBUG:root:EOF received
DEBUG:root:done
DEBUG:asyncio:Close <_WindowsSelectorEventLoop running=False closed=False debug=True>
sys:1: ResourceWarning: unclosed <socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto
=6, laddr=('127.0.0.1', 63858), raddr=('127.0.0.1', 7001)>
C:\Program Files (x86)\Python36-32\lib\asyncio\selector_events.py:631: ResourceWarning: unclosed transport <_SelectorSoc
ketTransport closing fd=240>
  source=self)
class ClientConnection(asyncio.Protocol):
    def connection_made(self, transport):
        logging.debug("connection made, calling write eof")
        transport.write_eof()
        logging.debug("after calling write eof, calling close")
        transport.close()
        logging.debug("after calling close")

    def connection_lost(self, exception):
        logging.debug("connection lost")
        super().connection_lost(exception)
import asyncio
import logging

import warnings


class ClientConnection(asyncio.Protocol):
    def connection_made(self, transport):
        logging.debug("connection made, sending and calling write eof")
        transport.write(b'hello')
        transport.write_eof()
        logging.debug("after calling write eof")

    def data_received(self, data):
        logging.debug("Got: {}".format(data))
        super().data_received(data)

    def connection_lost(self, exception):
        logging.debug("connection lost")
        super().connection_lost(exception)
        loop.stop()


def test_echo(ip, port):
    logging.debug("Creating connection: {}:{}".format(ip, port))
    co = loop.create_connection(ClientConnection, ip, port)
    logging.debug("Starting loop...")
    print(loop.run_until_complete(co))
    logging.debug("...create_connection done, running loop forever...")
    loop.run_forever()
    logging.debug("Loop stopped")

    logging.debug('----------------')


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    warnings.simplefilter('always')  # enables ResourceWarning

    loop = asyncio.get_event_loop()
    loop.set_debug(True)

    test_echo('127.0.0.1', 7001)
    test_echo('54.175.103.105', 30000)

    logging.debug("done")
    loop.close()