2012-10-07 8 views
5

저는 Linux에서 여러 클라이언트의 동시 읽기/쓰기 작업을 지원해야하는 서버를 작성하고 있습니다. select 기능을 사용하여 읽기/쓰기 가용성을 관리하고 싶습니다."선택"기능과 함께 비 차단 소켓을 사용하면 어떤 이점이 있습니까?

이해가 안되는 점은 : 소켓에 데이터를 읽을 수있을 때까지 기다리고 싶다고 가정 해 봅시다. select에 대한 설명서에는 읽을 수있는 데이터가있을 때까지 차단되고 읽기 기능이 차단되지 않는다고 명시되어 있습니다.

select를 사용하고 있고 읽기 기능이 차단되지 않는다는 것을 알고 있다면 소켓을 비 차단으로 설정해야하는 이유는 무엇입니까?

답변

6

소켓이 준비 상태로보고 될 때까지 검사 할 때까지 상태가 변경 될 수 있습니다.

좋은 예는 연결을 수락하는 것입니다. 새로운 연결이 도착하면 청취 소켓이 읽기 준비 상태로보고됩니다. 수락을 요청할 때까지 상대방이 아무 것도 보내기 전에 그리고 우리가 accept을 호출하기 전에 연결이 닫힐 수 있습니다. 물론이 경우의 처리는 OS에 따라 다르지만, 새로운 연결이 설정 될 때까지 accept이 단순히 차단되므로 응용 프로그램이 다른 소켓 처리를 막기 위해 무기한의 시간을 기다릴 수 있습니다. 청취 소켓이 비 차단 모드에있는 경우 이는 발생하지 않으며 EWOULDBLOCK이나 다른 오류가 발생하지만 accept은 차단되지 않습니다.

일부 커널은 (지금 수정 되었으면 좋겠다) UDP 및 select과 관련된 흥미로운 버그가 있습니다. 데이터 그램이 도착하면 select은 데이터 그램이 읽기 준비 상태로 표시된 소켓에서 깨어납니다. 데이터 그램 체크섬 유효성 검사는 사용자 코드가 recvfrom (또는 UDP 데이터 그램을 수신 할 수있는 다른 API)을 호출 할 때까지 연기됩니다. 코드에서 recvfrom을 호출하고 유효성 검사 코드가 체크섬 불일치를 감지하면 데이터 그램은 단순히 삭제되고 recvfrom은 다음 데이터 그램이 도착할 때까지 차단됩니다. 이 문제를 해결하는 패치 중 하나 (문제 설명과 함께)는 here입니다.

2

장점 중 하나는 프로그래밍 오류를 잡아낼 수 있다는 것입니다. 일반적으로 사용자를 차단하는 소켓을 읽으 려하면 EWOULDBLOCK이 대신 생기기 때문입니다. 소켓 이외의 객체의 경우 정확한 API 동작이 변경 될 수 있습니다 (http://www.scottklement.com/rpg/socktut/nonblocking.html 참조).

+0

아하, 고마워. :) – CaptainCodeman

1

이렇게 소리가 나기는 하겠지만 그렇지 않습니다. 차단하지 않도록하는 가장 좋은 이유는 차단하지 않기 때문입니다.

생각해보십시오. select()은 읽어야 할 것이 있지만 얼마나 있는지 모른다고 알려줍니다. 2 바이트 일 수도 있고 2,000 일 수도 있습니다. 대부분의 경우 select으로 돌아 가기 전에 어떤 데이터 가든 배수하는 것이 더 효율적입니다. 따라서 while 루프를 입력하여 읽을 수 있습니다.

while (1) 
{ 
    n = read(sock, buffer, 200); 
    //check return code, etc 
} 

읽을 내용이 없을 때 마지막으로 읽은 내용은 어떻게됩니까? 소켓이 비 블로킹 (non-blocking)이 아니면 블럭킹하여 select()의 포인트를 (적어도 부분적으로) 물리 칠 수 있습니다.

3

다른 사람이 언급 한 커널 버그 외에도 폴링 루프가 있더라도 논 블로킹 소켓을 선택하는 다른 이유는 빠른 도착 데이터로 성능을 향상시킬 수 있다는 것입니다. 블로킹 소켓이 "읽기 가능"으로 표시되면 어떻게되는지 생각해보십시오. 얼마나 많은 데이터가 도착했는지 모르기 때문에 한 번만 안전하게 읽을 수 있습니다.그런 다음 이벤트 루프로 돌아가서 소켓이 여전히 읽을 수 있는지 여부를 폴러에서 확인해야합니다. 즉, 소켓을 읽거나 쓸 때마다 시스템 호출을 두 번 이상 두 번 수행해야합니다. 읽는 것이 안전하다는 것을 알려주는 select과 읽기/쓰기 호출 자체를 의미합니다.

비 차단 소켓을 사용하면 첫 번째 수신 이후 select으로 불필요한 호출을 건너 뛸 수 있습니다. 소켓에 select으로 읽을 수있는 플래그가 지정되면 데이터를 반환하는 한 소켓에서 읽을 수있는 옵션이 제공되므로 빠른 데이터 버스트 처리 속도가 빨라집니다.

+0

고마워, 아주 좋은 지적, 나는 읽는 것을 시도하는 것이 다른 선택보다 더 빠를 것임을 몰랐다. – CaptainCodeman

관련 문제