문제

while (xxx) {
    timeout.tv_sec=TIMEOUT;
    timeout.tv_usec=0;
    FD_ZERO(&set); 
    FD_SET(sd,&set);

    switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout))
    xxxxx
}

그러나 잘 작동합니다

FD_ZERO(&set); 
FD_SET(sd,&set);

while (xxx) {
    timeout.tv_sec=TIMEOUT;
    timeout.tv_usec=0;

    switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout))
    xxxxx
}

그렇지 않습니다. 처음으로 작동하지만 다음에 while 루프를 통과 할 때 SD 소켓이 데이터를 수신하더라도 타임 아웃이됩니다. 나는 매번 비우고 세트를 채워야하는 자원 낭비 인 것 같습니다.

누구든지 이것이 왜 이것이 피해야하는지 제안하는 이유를 잘 설명하고 있습니까?

도움이 되었습니까?

해결책

선택한 인수를 수정하십시오. 당신은 정말로 매번 그것을 다시 시작해야합니다.

오버 헤드에 대해 우려하는 경우 커널에서 전체 FD_SET를 처리하는 비용은 FD_Zero 비용보다 다소 더 중요합니다. 커널 처리를 최소화하기 위해 FD_SETSZIZE가 아닌 최대 FD에서만 전달하려고합니다. 예에서 :

switch (select((sd + 1),&set,NULL,NULL,&timeout))

다수의 FDS가있는 더 복잡한 사례의 경우 일반적으로 최대 변수를 유지하게됩니다.

FD_SET(sd,&set);
if (sd > max) max = sd;
... repeat many times...

switch (select((max + 1),&set,NULL,NULL,&timeout))


많은 파일 설명자가 있고 Schlepping의 오버 헤드에 대해 우려하는 경우 select ()의 대안 중 일부를 살펴 봐야합니다. 당신은 당신이 사용하고있는 OS를 언급하지 않지만, 유닉스와 같은 OS의 경우 몇 가지가 있습니다.

  • Linux의 경우 epoll ()
  • freebsd/netbsd/openbsd/macos x, kqueue ()
  • Solaris, /dev /poll

API는 다르지만 모두 활성 파일 설명 세트를 유지하기 위해 본질적으로 상태 가득한 커널 인터페이스입니다. FD가 세트에 추가되면 계속해서 다시 전달하지 않고도 해당 FD의 이벤트를 통보 받게됩니다.

다른 팁

Select Man Page를 읽으십시오. 반환 된 세트는 사용할 준비가 된 파일 설명자입니다. FD_ISSET을 사용하여 설정되었는지 여부를 확인해야합니다.

FD_SET을 사용하기 직전에 항상 초기화하십시오.

그것이 Select가 작동하는 방식입니다. 하나 이상의 소켓이 있다면 가장 잘 작동하며 더 의미가 있습니다. 그것은 일종의 요점입니다 : 당신은 많은 소켓을 통해 선택하고 있습니다. 하나의 소켓에서 읽으려면 읽거나 읽으십시오.

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