문제

다음 코드는 Windows에서 올바르게 작동하지 않지만 Linux에서는 다음과 같습니다.

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setblocking(True)
    sock.connect(address)
    gobject.io_add_watch(
            sock.fileno(),
            gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP,
            callback)

Glib 소스의 다양한 장소에서 주석 스 니펫 및 기타 장소에서는 Windows에서 소켓이 폴링 중에 비 차단 모드에 놓여 있다고 언급합니다. 결과적으로 콜백 self.outgoing_cb 이 오류 메시지로 지속적으로 호출되며 소켓에 쓰기가 실패합니다.

[Errno 10035] A non-blocking socket operation could not be completed immediately

부름 sock.setblocking(True) 글을 쓰기 전에 이것을 우회하지 않는 것 같습니다. 폴링의 우선 순위를 낮추고 오류 메시지를 무시함으로써 예상대로 작동하지만 많은 이벤트에 멀리 던지고 많은 CPU를 소비합니다. Windows 에서이 한계에 대한 방법이 있습니까?

업데이트

나는 여론 조사의 요점이 POLLOUT 당신이 쓰기 전화를 할 때 당신은 얻지 못할 것입니다 EAGAIN/EWOULDBLOCK. 내가받는 이상한 오류 메시지는이 두 오류 코드와 동등한 Windows라고 생각합니다. 다시 말해서, 나는 얻는다 gobject.IO_OUT 소켓이 내가 성공적으로 쓸 수없는 이벤트, 그리고 차단 모드에 넣으면 여전히 부적절한 오류가 발생합니다.

다른 업데이트

이것이 올바르게 작동하는 Linux에서는 소켓이 차단 모드로 전환되지 않으며 수신합니다. IO_OUT, 소켓이 차단하지 않고 쓰여지거나 오류를 던질 때. 이 기능은 Windows에서 가장 잘 모방/복원하고 싶은 기능입니다.

추가 메모

에서 man poll:

   poll()  performs a similar task to select(2): it waits for one of a set
   of file descriptors to become ready to perform I/O.
          POLLOUT
                 Writing now will not block.

에서 man select:

A file descriptor  is considered ready if it is possible to perform the corre‐
sponding I/O operation (e.g., read(2)) without blocking.
도움이 되었습니까?

해결책

비 블로킹 I/O를 수행하는 데 문제가 있습니까? 차단 I/O를 사용하는 경우 폴링 루프를 사용하는 것은 이상하게 보입니다.

이와 같은 프로그램을 작성할 때 다음을 수행하는 경향이 있습니다.

  • 버퍼 파일 디스크립터로 보내려는 바이트를 버퍼합니다.

  • 만 요구합니다 IO_OUT (아니면 그 poll() 동등한, POLLOUT) 해당 버퍼가 비어 있지 않은 이벤트.

  • 언제 poll() (또는 이와 동등한)는 글을 쓸 준비가되었다고 신호를 보냈습니다. 당신이 얻는다면 EAGAIN/EWOULDBLOCK, 버퍼에서 성공적으로 쓴 바이트를 제거하고 다음에 신호를받을 때 기다리십시오. 전체 버퍼를 성공적으로 작성한 경우 요청을 중단하십시오. POLLOUT 그래서 당신은 의심스럽게 일어나지 않습니다.

(내 생각에 Win32 바인딩이 wsaeventSelect 그리고 WaitForMultipleObjects() 시뮬레이션 poll(), 그러나 결과는 동일합니다 ...)

차단 소켓에서 원하는 접근 방식이 어떻게 작동하는지 잘 모르겠습니다. 당신은 쓸 수있을 때 당신을 깨우라고 요청했기 때문에 당신은 끊임없이 "깨어납니다". 당신은 글을 쓸 데이터가있을 때만 지정하고 싶지만 ... 깨어날 때 시스템이 실제로 당신에게 말하지 않을 것입니다. 얼마예요 차단하지 않고 쓸 수있는 데이터이므로 블로킹이 아닌 I/O를 사용하는 좋은 이유입니다.

다른 팁

지오 포함 Gsocket, 2.22 이후 "낮은 레벨 네트워크 소켓 객체". 그러나 이것은 아직 포팅되지 않았습니다 창문에 피그 벡터.

이것이 도움이 될지 확실하지 않습니다 (설문 조사 기능이나 MFC 소켓에 능숙하지 않으며 폴링이 귀하의 프로그램 구조의 요구 사항이라는 것을 모릅니다) 따라서 소금 한 알로 가져 가십시오.

그러나 쓰기시 차단 또는 eagain을 피하기 위해 Select를 사용합니다. 즉, Select가 전달되는 쓰기 세트에 소켓을 추가하고 Select ()가 RC = 0으로 돌아 오면 소켓이 즉시 쓰기를 허용합니다 ...

우리가 앱에서 사용하는 쓰기 루프는 (pseudocode)입니다.

set_nonblocking.
count= 0.
do {
   FDSET writefds;
   add skt to writefds.
   call select with writefds and a reaonsable timeout.
   if (select fails with timeout) {
       die with some error;
   } 

   howmany= send(skt, buf+count, total-count).
   if (howmany>0) {
       count+= howmany.
   }
} while (howmany>0 && count<total);

당신은 사용할 수 있습니다 꼬인, 여기에는 포함됩니다 GTK 지원 (창에서도) 모든 여러 블로킹되지 않은 소켓이 Windows의 오류 조건이 높아지는 것을 좋아합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top