2016-06-29 3 views
0

Ich wollte das neue Modul asyncio von Python 3.5.1 ausprobieren. Hier ist mein Testcode:Asyncio: Probleme mit sehr einfachen UDP-Client zum Schreiben und Trennen

import asyncio 

class EchoClientProtocol: 
    def __init__(self, message, loop): 
     self.message = message 
     self.loop = loop 
     self.transport = None 

    def connection_made(self, transport): 
     self.transport = transport 
     print('Send:', self.message) 
     self.transport.sendto(self.message.encode()) 
     self.transport.close() 

    def datagram_received(self, data, addr): 
     print("Received:", data.decode()) 

     print("Close the socket") 
     #self.transport.close() 

    def error_received(self, exc): 
     print('Error received:', exc) 

    def connection_lost(self, exc): 
     print("Socket closed, stop the event loop") 
     loop = asyncio.get_event_loop() 
     loop.stop() 

loop = asyncio.get_event_loop() 
message = "Hello World!" 
connect = loop.create_datagram_endpoint(
    lambda: EchoClientProtocol(message, loop), 
    remote_addr=('127.0.0.1', 9999)) 
transport, protocol = loop.run_until_complete(connect) 
loop.run_forever() 
transport.close() 
loop.close() 

Als ich dies ausführen, der Dolmetscher gibt mir:

Traceback (most recent call last): 
    File "C:\Users\oxygen\Documents\GitProjects\tests\python\udp\client.py", line 
35, in <module> 
    loop.run_forever() 
    File "C:\Python35-32\lib\asyncio\base_events.py", line 295, in run_forever 
    self._run_once() 
    File "C:\Python35-32\lib\asyncio\base_events.py", line 1218, in _run_once 
    event_list = self._selector.select(timeout) 
    File "C:\Python35-32\lib\selectors.py", line 314, in select 
    r, w, _ = self._select(self._readers, self._writers, [], timeout) 
    File "C:\Python35-32\lib\selectors.py", line 305, in _select 
    r, w, x = select.select(r, w, w, timeout) 
OSError: [WinError 10038] an operation was attempted on something that is not a socket 

Ich denke, das durch die Folge von self.transport.sendto(self.message.encode()) und self.transport.close() verursacht wird. Wenn ich richtig verstehe, ist die sendto-Methode asynchron und wird tatsächlich aufgerufen, nachdem ich den Socket durch Aufruf der close-Methode geschlossen habe. Gibt es eine Möglichkeit, dies zu lösen?

Antwort

0

Die DatagramTransport (eigentlich _SelectorDatagramTransport) Pläne zwei Aktionen auf der Verbindung, die erste ist connection_made aus gegebenen Protokoll, das zweite ist _read_ready (recvfrom) - in dieser Reihenfolge (https://github.com/python/asyncio/blob/master/asyncio/selector_events.py#L996).

Da Sie den Transport unter connection_made schließen, schlägt die folgende Aktion fehl (_read_ready). Entfernen Sie self.transport.close() von dort.

Sie könnten interessant die asyncio udp examples finden.

+0

Hey, danke für deinen Kommentar! Mein Code ist eigentlich eine bearbeitete Version des von Ihnen verlinkten Beispiels. Könnten Sie bitte etwas mehr Hilfe geben, wie Sie die Verbindung ohne die Leseaktion öffnen können? Ich möchte wirklich nur die Verbindung herstellen, Daten senden und schließen. Ich habe versucht, Hilfe in den Dokumenten zu finden, und ich fand [diese Methode] (https://docs.python.org/3/library/asyncio-stream.html#asyncio.open_connection), würde mir das helfen? –

+0

UDP ist verbindungsloses Protokoll (https://en.wikipedia.org/wiki/User_Datagram_Protocol) – kwarunek

Verwandte Themen