티스토리 뷰

이 프로그램은 문제가 발생하지 않는 클라이언트 프로그램이므로 이 프로그램을 활용하면 웬만한 상황은 모두 커버할수 있다.

그렇기 때문에 거의 외우다 시피 알아두는것이 좋을것 같다.



먼저 for문 윗부분을 살펴보자.

stdineof 라는것은 일종의 flag인데 클라이언트에서 파일을 읽다가 EOF가 발생하거나 키보드로부터 입력을 받다가 Ctrl+d가 입력 되어서 EOF가 발생하면 이 flag에 1이라는 값이 세팅 되게끔 만들어 놓은 것이다.


stdineof == 0 이라는 것은 아직 클라이언트에서 EOF가 발생하지 않았다는 것이기 때문에 그 다음 줄에서

FD_SET을 통해서 그 파일 디스크립터를 rset이라는 읽기 전용 파일 보따리에 추가해서 그 파일이 데이터를 읽을 준비가 됬는지를 검사하게 된다.

stdineof == 1이라는것은 클라이언트에서 EOF가 발생해서(더이상 보낼 데이터가 없다) FIN을 서버에게 보냈다.


FIN을 보냈다는 것의 의미는 클라이언트가 보낼 데이터도 없고 에코프로그램인 서버 프로그램도 더이상 클라이언트에게 보낼 데이터도 없다는 것이다. stdineof == 1인 상황은 클라이언트도, 서버도 서로 지금까지 보낸 데이터들 말고 앞으로 보낼 데이터에 대해서는 보낼 데이터가 없다는 것을의미한다. 


그렇기 때문에 stdineof == 0 이라면 아직 클라이언트와 서버가 서로 데이터를 송수신 하고 있다는 의미이므로, 

클라이언트 소켓에 데이터가 오는지 안오는지 검사를 해야 한다 따라서 FD_SET을 stdineof ==0 일때만 해주어야 하는 것이다.


maxfdp1이라는 정수 값은 앞에서 설명했듯이 select의 첫번째 매개변수인 몇개의 파일을 검사할것인지를 나타내기 위함이다

+1을 해주는 이유는 파일 디스크립터가 0번부터 시작하기 때문에 4번 fd까지 있을때 총 5개의 파일이 존재하기 때문이다.


그리고 나서 select시스템콜을 호출해서 읽기 전용 파일 보따리에 파일들에 데이터가 수신되면 깨어나고 그 동안은 블락 되게끔 한다.


만약에, 읽기 전용 파일 보따리(rset)에서 소켓(파일의 일종)이 읽을 준비가 되었기 때문에 select가 블락에서 깨어났냐 물어보는

FD_ISSET이 true를 리턴하게 된다면, 그 소켓에 대해서 read를 해야 할 것이다.

하지만 소켓이 readable하는 상황은 그 소켓에 FIN메세지가 온 경우도 포함 되기 때문에, FIN이 온 경우는 n == 0을 물어보는 if문에서

처리해주고, FIN때문에 소켓이 셀렉트로부터 깨어난게 아닌 경우에는 그냥 서버로부터 온 데이터를 출력해주면 그만이다.


만약 소켓에 FIN이 와서 select가 블락에서 깨어난 것에도 이런 경우가 있을 수 있다.


1. 내가 FIN을 보내고 나서 나는 더이상 데이터를 보낼게 없다라는 의사표시를 한 다음 상대로부터 FIN을 받은경우

2.내가 FIN을 보내지 않았는데 상대방이 더이상 보낼게 없다고 FIN으로 의사표시 한 경우.


첫번째 if문인 stdineof == 1이라는것의 의미는 이미 클라이언트에서 EOF가 발생했다는 것이고 그 뜻은 shutdown으로 

이미 FIN을 서버로 보냈다는 것이다.


이상황에서 FIN을 받았기 때문에 if(read==0)가 true 된것이므로, 이 경우에는 정상 종료 시키면 아무 문제가 없다 그래서 그냥 return;을 해주고 있다.

(1번 경우에 해당함, 클라이언트가 먼저 하프 클로즈하고 서버가 나중에 하프 클로즈 한 경우)


만약 클라이언트에서 EOF가 발생하지 않았는데 서버로부터 FIN이 온 경우가 else문에 해당한다. 

이 경우에는 서버가 종료되었다는 메세지를 클라이언트 모니터에 출력해주고 클라이언트를 종료 시키면 된다.

(2번 경우)




소켓이 아닌 키보드 또는 어떤 파일이 readable해 졌기 때문에 select에서 깨어났다고 했을때가 위의 사진이다.


키보드 또는 파일도 마찬가지로 ctrl+d를 입력하거나  파일의 끝을 만나 EOF가 발생한 경우 select는 그 파일들이 readable해졌다고 판단해서 블락에서 깨어나게 된다. 안쪽 첫번째 if문이 바로 위의 상황을 구분하기 위함이다. read가 0과 같다는 것은 EOF를 만났다는 것이다.


클라이언트에서 EOF가 발생한 경우 stdineof 라는 flag에 1을 세팅해서 이 프로그램에서 eof가 발생했다는 것을 공유 변수에 넣고,

shutdown시스템콜로 프로세스는 종료하지만 소켓은 유지한상태로 FIN을 서버에게 보내게 된다. 


그리고 나서 더이상 그 파일 포인터는 readable한지 안한지 검사할 필요가 없게 된다.(그 파일에 대해 EOF가 발생한 상태이므로) 그리하여 마지막으로 FD_CLR로 파일 보따리에서 그 파일을 꺼내고 continue;를 통해서 파일 보따리의 다른 파일들이 readable해졌는지 반복적으로 검사 하게 된다.

'컴퓨터 공학과 졸업 > 소켓 프로그래밍' 카테고리의 다른 글

poll시스템콜  (0) 2017.11.13
개선된 서버 프로그램  (0) 2017.11.11
shutdown  (0) 2017.11.10
I/O 멀티플렉싱(select)  (0) 2017.11.09
I/O모델들과 I/O 멀티플렉싱(select)  (0) 2017.11.08
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함