2012-02-23 2 views
1

사람처럼) (선택 사용하여 나에게 몇 가지 코드를 보여 그래서 난 완전히 이성을 잃었을 : 그러니까 기본적으로 소켓 파일을 삽입 바인드 후 무엇을 FD_ZERO 어떤 이유로 명확 이전 내용입니다 듣고 말하는소켓 파일 설명

FD_ZERO(&readfds); 
FD_SET(socket,&readfds); 
FD_SET(0,&readfds); 
.......// bind() and listen(),regular stuff 
// Before select(),this guy cleared readfds to null and sort of start all over again 
FD_ZERO(&readfds);// Behold,this is exactly the line confusing myself 
FD_SET(socket,&readfds); 
// select will be called in the future within a infinite loop 

fd가 다시 설정됩니다. 반면에 fd가 설정되면 0 설명자 (표준 입력)가 사라졌습니다.

누구든지이 모든 것을 설명 할 수 있습니까? 나는 이것이 정확하다고 느끼지 않지만 실제로는 그것을 이해할 수 없다. 어쩌면 몇 가지 구체적인 fd 세트를 다시 설치하는 것은 실질적인 메커니즘입니다.

bind()listen()은 fd를 몇 가지 방식으로 설정할 수 있다고 생각했습니다. 몇 가지 단절 점을 설정하고 outputs.Conunately를 검사합니다. fd 세트가 전혀 변경되지 않았습니다.

UPDATE :

정말로 나를 혼란하는 두 번째 FD_ZERO(&readfds)입니다. 분명히 첫 번째 것은 버퍼에서 녹슨 물건을 청소하는 것과 같습니다. 매 반복마다 fdset을 기본값으로 초기화해야합니다. 나는 두 번째 것을 이해하지 못한다. 어느 것이 든 잘못된 것이거나 어쨌든 상처를 입지 않을 것입니다.

+1

'select'는 fdset을 변경하지만'bind'와'listen'은 변경할 수 없습니다. 포인터도 주어지지 않습니다. 그러나'poll'이나'epoll'과 같은 현대적인 API를 사용하고 호의를 베풀고 fdset에 대해 다시 걱정하지 마십시오. –

+0

시원하게 들리지만 방금 캔트가 끝납니다. – jasonkim

+1

'poll'을 사용하십시오. 현대적이고 휴대 성이 뛰어납니다. 'epoll'은 벤치 마크 자체 쾌락만을위한 것이며 벤치 마크는 실제로 사용되는 대부분의 요구 (epoll은 실제로'poll'보다 훨씬 느립니다)와 일치하지 않습니다. –

답변

4

혼란이 어디에 있는지 잘 모르지만 여기에 설명이 나와 있습니다.

fdset는 0에서 인덱스 파일 디스크립터의 비트 마스크입니다 (기술적으로, 나는 그것을 는 비트 마스크하지만 것 다른 구현 ... 이상한 수이 있다고 생각하지 않습니다).

있도록 fdset이 같은 수 있습니다 :

   Byte 0        Byte 1 
+---+---+---+---+---+---+---+---+ +---+---+----+----+----+----+----+----+ 
|fd0|fd1|fd2|fd3|fd4|fd5|fd6|fd7| |fd8|fd9|fd10|fd11|fd12|fd13|fd14|fd15| 
+---+---+---+---+---+---+---+---+ +---+---+----+----+----+----+----+----+ 

을 아이디어는 주어진 전략 중 당신이에 관심이 있다면 (파일 기술자)의 비트를 설정한다는 것이다. 당신이 그것에 관심이 없다면, 당신은 조금 분명히 둡니다.

FD_ZERO은 모든 비트를 지우므로 좋은 시작점입니다. 그런 다음 두 FD_SET 호출은 fd0 (표준 입력) 및 fd<socket>의 비트를 설정합니다. 두 소켓 표준 입력 또는 조치 (select에 fdset를 통과 할 때 사용하는 매개 변수 위치에 대한 조치의이 달려 것 유형에 대한 조치가 발생했을 경우

그런 다음, 그 fdset를 사용하여 선택 호출이 반환합니다. 합격을 읽기 fdset은 소켓을 읽을 수 있거나 표준 입력 (예 : 키보드를 사용하는 사용자)에서 읽을 수있는 경우 리턴합니다.

이것은 코드에서 유용 할 수 있습니다. "채팅"응용 프로그램은 상대방이 자신이나 친구의 입력을 기다릴 것이기 때문에 사용하십시오.

fdset에서 비트를 다시 제로 설정하고 다시 설정하는 것은 select 자체가 해당 동작을 감지 한 fd (또는 fds)를 나타내도록 세트를 수정하기 때문입니다.

예 : 소켓을 통해 들어 왔지만 표준 입력을 통해 아무 것도 입력되지 않으면 fdset이 select에 의해 수정되어 해당 비트 만 설정됩니다. 그렇게하면 FD_ISSET을 사용하여 어떤 fds를보아야하는지 감지 할 수 있습니다.당신이 의견을 시사로서, 다음 두 FD_ZERO()/FD_SET() 시퀀스 사이 (readfds를 사용하거나 다른 호출) select 통화가없는 경우


은, 네, 첫 번째가 있기 때문에, 불필요한 것 같습니다 정보는 두 번째 정보로 덮어 씁니다.

전체 코드 또는 건축 디자인 문서 :-)를 보지 않고도 알기가 어렵습니다.

+0

나를 혼란스럽게하는 것은 실제로 코드를 지우고 스스로를 두 번 읽는 것입니다. – jasonkim

+0

@ y26jin, 왜냐하면'select'가 배열을 수정하기 때문입니다 - 그걸 확장하기위한 답을 추가했습니다. – paxdiablo

+0

두 번째 것은 select()를 호출하기 전에 호출되었습니다. – jasonkim

1

Select()은 동시에 여러 소켓을 수신 대기하는 경우에 사용됩니다. socket 연결을 accept() 할 때마다 socket descriptor가 반환되고 이것을 사용하여 파일을 보내고받습니다.

FD_SET을 수행하면 소켓 설명자가 세트에 추가됩니다 (읽기/쓰기 가능). FD_ZERO은 해당 특정 세트의 모든 항목을 지 웁니다.

본질적으로 연결을 수락 할 때마다 소켓 설명자를 집합에 추가 할 수 있습니다 (즉, 소켓을 사용하여 읽기/쓰기를 수행하려는 경우).

select() 함수를 호출 할 때 사용할 세트를 지정하십시오. (예 : readfds)와 select()은 이미 해당 세트 (readfds)에있는 모든 소켓을 폴링합니다.

더 명확히하기 위해 beej's guide to network programing을 읽으십시오. 배우기 좋은 튜토리얼.

0

select(2)은 인수 fd 세트를 수정하므로 반복 할 때마다 초기화해야합니다.