2015-01-20 3 views

답변

1

BaseEventLoop에 대해 정의 된 하위 수준의 소켓 작업에는 socket.socket 개체가 전달되어야합니다. BaseEventLoop.sock_recv(sock, nbytes). 따라서 socket.socket이 있으니 sock.recv_into()으로 전화 할 수 있습니다. 그것을하는 것이 좋은 생각인지 여부가 또 하나의 질문입니다. 지금 asyncio .recv_into() 아웃 - 박스를 사용하는 방법을되지 않았습니다

+0

이미'loop.sock_recv'을 사용하고 있습니다. 그러나'loop.sock_recv'는 bytes 객체를 반환합니다. 그래서 저는'bytearray.extend method'도 사용합니다. ex) 'ba = bytearray(); bytes_object = yield from loop.sock_recv (some_sock); ba.extend (bytes_object) ' 'sock_recv'는 사전 생성 된 고정 크기 'bytearray'를 사용하지 않습니다. –

+0

나는'precreated_buffer = bytearray (b ''* 100)와 같은 방식을 원한다. loop.sock_recv_into (some_socket, precreated_buffer, 100)' –

+0

@SungHyunHwang : 나는'loop.sock_recv()'대신에''socket.recv_into()'_를 소켓에 호출 할 수 있다고 제안했다. 나는 그것이 asyncio 프레임 워크 내에서하는 것이 안전한 것인지 전혀 모른다 - 나는 의심한다. – mhawke

1

당신 , .recv_into() 기능을 이용하여 자신의 asyncio 전송을 구현하지만, 예 수 있습니다.

개인적으로 나는 매우 큰 스피드 업에 의문을 가지고 있습니다. C로 개발할 때 제로 카피는 매우 중요하지만 파이썬 이점과 같은 고급 언어는 훨씬 적습니다.

0

업데이트 :이 글을 쓰면서 알파 버전 인 Python 3.7.0부터 표준 라이브러리의 asyncio 모듈은 AbstractEventLoop.sock_recv_into()를 문서화합니다. 같은 요청에 따라

호출의 asyncio 할 ... 답을 확장 sock_recv_into()은 일반적으로 보인다 :

편집

byte_count = await loop.sock_recv_into(sock, buff) 

버프는 파이썬의 버퍼 프로토콜을 구현하는 변경 가능한 개체입니다, 예는의를 포함 bytearray 및 bytearray에 memoryview. 아래 코드는 메모리 뷰를 사용하여 bytearray에 수신하는 방법을 보여줍니다.

asyncio 소켓의 데모 코드에는 연결의 양쪽을 설정하고 이벤트 루프를 실행하는 일련의 스 캐 폴딩이 필요합니다. 요점은 아래의 sock_read_exactly() 공동 루틴에서 asyncio의 sock_recv_into()를 사용하는 것입니다.

#!/usr/bin/env python3 

"""Demo the asyncio module's sock_recv_into() facility.""" 

import sys 
assert sys.version_info[:2] >= (3, 7), (
     'asyncio sock_recv_into() new in Python 3.7') 

import socket 
import asyncio 

def local_echo_server(port=0): 
    """Trivial treaded echo server with sleep delay.""" 
    import threading 
    import time 
    import random 
    ssock = socket.socket() 
    ssock.bind(('127.0.0.1', port)) 
    _, port = ssock.getsockname() 
    ssock.listen(5) 
    def echo(csock): 
     while True: 
      data = csock.recv(8192) 
      if not data: 
       break 
      time.sleep(random.random()) 
      csock.sendall(data) 
     csock.shutdown(1) 
    def serve(): 
     while True: 
      csock, client_addr = ssock.accept() 
      tclient = threading.Thread(target=echo, args=(csock,), daemon=True) 
      tclient.start() 
    tserve = threading.Thread(target=serve, daemon=True) 
    tserve.start() 
    return port 


N_COROS = 100 
nrunning = 0 

async def sock_read_exactly(sock, size, loop=None): 
    "Read and return size bytes from sock in event-loop loop." 
    if loop is None: loop = asyncio.get_event_loop() 
    bytebuff = bytearray(size) 
    sofar = 0 
    while sofar < size: 
     memview = memoryview(bytebuff)[sofar:] 
     nread = await loop.sock_recv_into(sock, memview) 
     print('socket', sock.getsockname(), 'read %d bytes' % nread) 
     if not nread: 
      raise RuntimeError('Unexpected socket shutdown.') 
     sofar += nread 
    return bytebuff 

async def echo_client(port): 
    "Send random data to echo server and test that we get back the same." 
    from os import urandom 
    global nrunning 
    loop = asyncio.get_event_loop() 
    sock = socket.socket() 
    sock.setblocking(False) 
    await loop.sock_connect(sock, ('127.0.0.1', port)) 
    for size in [1, 64, 1024, 55555]: 
     sending = urandom(size) 
     await loop.sock_sendall(sock, sending) 
     received = await sock_read_exactly(sock, size) 
     assert received == sending 
    nrunning -= 1 
    if not nrunning: 
     loop.stop() 


if __name__ == '__main__': 
    port = local_echo_server() 
    print('port is', port) 
    loop = asyncio.get_event_loop() 
    for _ in range(N_COROS): 
     loop.create_task(echo_client(port)) 
     nrunning += 1 
    print('Start loop.') 
    loop.run_forever() 
+0

'AbstractEventLoop.sock_recv_into()'를 사용 하시겠습니까? 아마도 코드 샘플을 포함 할 것입니다. –