2014-03-07 2 views
4

here의 코드를 사용하여 UDP 펀칭을 테스트하고 있습니다. 그것은 리눅스에서 작동하지만 Windows에서 오류를보고합니다.python select.select() on Windows

while True: 
    rfds, _, _ = select([0, sockfd], [], []) # sockfd is a socket 
    if 0 in rfds: 
     data = sys.stdin.readline() 
     if not data: 
      break 
     sockfd.sendto(data, target) 
    elif sockfd in rfds: 
     data, addr = sockfd.recvfrom(1024) 
     sys.stdout.write(data) 

그리고 오류 MSG를 : 여기에 오류가 발생하는 코드이다

Traceback (most recent call last): 
    File "udp_punch_client.py", line 64, in <module> 
    main() 
    File "udp_punch_client.py", line 50, in main 
    rfds, _, _ = select([0, sockfd], [], []) 
select.error: (10038, '') 

이 오류는 Windows에서 select 구현해야 할 몇 가지 일을 가지고 알고, 모두 인용이 :

참고 Windows의 파일 개체는 허용되지 않지만 소켓은 있습니다. Windows에서 기본 select() 함수는 WinSock 라이브러리에서 제공되며 WinSock의 이 아닌 파일 설명자를 처리하지 않습니다.

  1. [0, sockfd]에서 0은 무엇을 의미 하는가 :

그래서 나는 두 가지 질문 있어요? 이것은 일종의 자주 사용되는 기법입니까?
  • select이 Windows의 socket에서만 작동하는 경우 Windows와 호환되는 코드를 만드는 방법은 무엇입니까?
  • 감사합니다.

    +1

    '0'은'stdin'의'fd'입니다. [File Descriptors] (http://en.wikipedia.org/wiki/File_descriptor) – tmr232

    +0

    @ tmr232 코드를 수정하는 방법은? – laike9m

    +0

    @ J.F.Sebastian Alright – laike9m

    답변

    4

    selectselect이 Windows의 스트림에서 작동하지 않으므로 stdin과 네트워크 이벤트를 하나의 스레드에서 처리하는 데 도움이되지 않습니다. 필요한 것은 차단없이 stdin을 읽는 방법입니다. 다음을 사용할 수 있습니다 :

    1. 여분의 스레드는 stdin입니다. 그것은 잘 작동해야하고 일을하는 가장 쉬운 방법입니다. 필요한 경우 I/O 이벤트를 기다리는 것만으로 파이썬 스레드 지원을 확실히 할 수 있습니다.
    2. gevent과 같은 greenlet 같은 메커니즘으로 쓰레드 지원과 대부분의 표준 라이브러리의 I/O 기능을 패치하여 이들이 그린 레츠를 차단하지 못하도록합니다. 또한 비 블로킹 파일 I/O를 제공하는 twisted (주석 참조)과 같은 라이브러리가 있습니다. 이 방법은 가장 일관성있는 방법이지만 프레임 워크 (twisted 또는 gevent, 그 차이는 중요하지 않음)와 일치하는 스타일을 사용하여 전체 응용 프로그램을 작성해야합니다. 그러나, 나는 twisted 래퍼가 Windows에서 stdin에서 비동기 입력을 할 수 없다고 생각합니다. (아마 그들은 * nix에서이를 수행 할 수 있습니다. 아마도 같은 select을 사용합니다).
    3. 다른 트릭입니다. 그러나, 가능한 속임수의 대부분은 오히려 추한 것입니다.
    +0

    최대한 빨리 답변 해 드리겠습니다. – laike9m

    +0

    +1 스레드는 Windows에서 가장 쉬운 경로 일 것입니다. 또한'twisted','asyncio' (튤립)이 있습니다. – jfs

    +0

    'asyncio'를보아야합니다. 'twisted '에 관해서는 훌륭한 라이브러리입니다 (일반적으로'twisted' 또는'gevent'를 사용하고 둘 다 좋아합니다). 그리고 네, 파일과 비슷한 객체를 감싸고 있습니다. 나는 그런 종류의 틀을 사용하는 것이 최선의 해결책이라고 생각합니다. 그러나 기존 코드에 대한 사소한 수정 만이 아닙니다. – Ellioh

    2

    답변에서 알 수 있듯이 입력 스트림을 처리 할 다른 스레드가 만들어져 작동합니다. 수정 된 코드는 다음과 같습니다.

    sock_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
    
    def send_msg(sock): 
        while True: 
         data = sys.stdin.readline() 
         sock.sendto(data, target) 
    
    def recv_msg(sock): 
        while True: 
         data, addr = sock.recvfrom(1024) 
         sys.stdout.write(data) 
    
    Thread(target=send_msg, args=(sock_send,)).start() 
    Thread(target=recv_msg, args=(sockfd,)).start() 
    
    +0

    'from threading import *'를 잊지 마십시오. – Luke