1

내가 읽으려는 일부 열린 연결로 선택 루프가 있고 전선을 통해 들어오는 물건을 파싱 할 각 연결에 상태 시스템이 연결되어 있다고 가정합니다. 옳은 일. 연결 중 하나 인 c이 준비되어 있고 선택 루프가 처리를 위해 상태 장치 m으로 연결한다고 가정 해 봅니다. 연결에서 10 바이트를 읽으 려하고 readpartial을 사용하려고합니다. 불행히도 우리는 6 바이트 만 받았습니다. 따라서 m은 6 바이트를 읽고 차단을 해제합니다. 다음에 루프가 우리에게 c을 건네고 11 바이트가 더 있습니다. m은 여전히 ​​선택 루프가 우리에게 c을 건네주는 마지막 상태 였고 더 많은 바이트를 읽어야하므로 readpartial(4)으로 4 바이트를 읽으므로 그 중 10 바이트를 사용하는 부작용이 발생합니다 그 버퍼와 새로운 상태로 전송합니다. m이 여전히 연결을 유지하므로 루프를 차단 해제하거나 새 상태가 지시하는 작업을 시작할 수 있으며 이러한 작업 중 하나는 readpartial과 관련된 것일 수 있습니다. 이 경우 올바른 작업은 readpartial이 차단되지 않으므로 연결 처리를 계속하는 것입니다. 그러나 일련의 동작이 있었다고 가정 해보십시오. 6 바이트를 수신하고, 6 바이트를 읽으며, & 블록을 해제하고, 4 바이트를 수신하고, 4 바이트를 읽습니다. & 몇 가지 일을하십시오. 이 경우 읽을 것이 아무것도 없으므로 상태 기계가 연결시 readpartial에 전화하기로 결정한 경우 바람직하지 않은 상황 인 선택 루프를 차단했을 것이며이 경우 올바른 것이 상태 일 것입니다 차단 해제하고 select 루프가 다시 돌아올 때까지 기다립니다.nio4r 선택 루프가있는 루비 소켓

select 루프를 차단하고 싶지 않고 연결 버퍼에 바이트를 남기고 싶지 않은 경우이 문제를 해결하기위한 정확하고 효율적인 방법은 무엇입니까? Ruby의 Socket 및 IO API를 읽었으며 읽을 물건이 있는지 여부를 알려주는 메소드를 찾을 수 없습니다. read_nonblock은 스트림을 읽을 수 있는지 여부를 테스트 할 수있는 잠재적 인 방법입니다. 예를 들어, char = c.read_nonblock(1); c.ungetc(char); wire_data = c.read_partial(10)wire_data == char으로 결과가 더 많아도 테스트를 수행 할 수 없습니다. 버퍼에 char보다 큽니다.

답변

1

평소처럼 문제를 해결하면서 해결책을 찾는데 도움이되었습니다. 상태 기계에 readpartial을 호출하는 대신 read_nonblock으로 전화하면됩니다. read_nonblock 읽을 것이 없으면이 예외를 throw하고 난 그냥이 예외를 catch하고 select 루프를 차단할 수 있습니다.