티스토리 뷰

서버에 있는 프로그램에서는 리슨 소켓을 만들고 나서 accept()시스템 콜을 호출한다. 


이 시스템 콜을 호출하게 되면 그 프로세스는 블락 되게 되며 (클라이언트로부터 3way 핸드쉐이크 요청이 올때까지) 클라이언트로 부터 요청이 들어오면 Incompleted Queue에 그 요청정보를 넣어 놓고 나서 다시 클라이언트에게 SYN+ACK를 보내준다. 

그리고 나서 클라이언트 프로그램에서 SYN+ACK를 받으면 connect()시스템콜이 정상적으로 리턴 되며 연결이 성공했다고 인지하게 되고 ACK를 다시 서버에게 보내준다. 


서버가 마지막 ACK를 받으면 Incompleted Queue에 있던 클라이언트의 연결 요청을 Completed Queue로 옮기게 되고 

이 큐에 옮겨 지고 나면, 서버의 커널이 블락 되어있던 프로세스를 깨우면서 새로운 connected소켓을 만들고 

서버와 클라이언트가 이 connected소켓을 통해서 데이터를 주고 받게 된다.


 Incompleted Queue가 꽉찬 상황에서 새로운 클라이언트가 연결 요청을 보내는 경우

서버 프로그램에서는 아무 처리도 하지 않고 그냥 그 패킷을 Discard(버리다) 해버린다. 

연결이 거절 되었다고 클라이언트에게 알려주지 않고 그냥 패킷을 버리기만 하는 이유?

-> 그래야 SYN메세지를 보낸 클라이언트가 서버로 부터 ACK를 받지 못해서 타임 아웃이 발생하고 SYN메세지를 재전송하게 된다.

-> 즉 서버에서 아무 처리를 안 해줌으로써 클라이언트가 반복적으로 연결요청을 시도하게끔 만들어서  Incompleted Queue가 비는 순간에 

언젠가는 연결요청이 성공하게끔 만들어 준것이다.


Incompleted Queue에 들어온 클라이언트의 연결요청 정보가 날라가는 경우

클라이언트가 SYN메세지를 보냈을때 연결요청정보를 Incompleted Queue에 넣고 나서 서버가 다시 SYN+ACK를 클라이언트에게 전송한다.

이때 SYN이 유실되었거나 클라이언트가 SYN+ACK는 제대로 받았지만 다시 서버에게 ACK를 보냈을때 그 ACK가 유실될 경우 서버 입장에서는 SYN를 보냈는데 ACK가 안오게 되는 것이다. 그래서 서버는 SYN+ACK를 다시 재전송 할것이다. 

(Incompleted Queue에 들어는 왔지만 타임아웃이 발생했다. -> Incompleted Queue엔트리에서 그 타임아웃 된 엔트리를 빼버린다.)


엔트리를 빼버렸는데 뒤늦게 ACK가 들어온 경우?

즉시 RESET메세지를 클라이언트에게 보내서 데이터를 전송하지 않게끔 해준다.

(Incompleted Queue에 니가 요청한 요청정보가 없다) -> 무슨 일에선가 커넥션이 안됬다는것을 클라이언트가 알게 되기 때문에 

데이터를 전송하지 않게 된다.



중요

accept()시스템콜은 서버에서 마지막 ack를 받은 후에 반환된다. listen()시스템 콜 호출후에 클라이언트로 부터 연결요청(SYN)을 받았다고 해서 accept()가 반환되는게아니다!!

연결요청이오면 단순히 SYN+ACK를 클라이언트에게 응답으로 보내주고 Incompleted Queue에 클라이언트의 요청 정보를 담는게 끝이다.

accept()는 Completed Queue에서 하나씩 연결요청을 받아들여 새로운 소켓을 만들고 

그 소켓으로 클라이언트와 데이터를 주고 받겠다는 뜻이다.


클라이언트 프로그램에서 클라이언트의 아이피와 포트번호를 소켓에 bind하지 않아도 되는 이유

-> connect()시스템콜 시 운영체제 커널이 알아서 IP는 컴퓨터의 IP로, 포트번호는 임의의 포트번호로 지정해준다.








댓글
최근에 올라온 글
최근에 달린 댓글
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
글 보관함