티스토리 뷰

TCP소켓을 사용할때 TCP의 정의에서 네트워크 상황을 커널은 알지만 유저프로세스는 거의 모르거나 극히 일부로 제한되는 경우가 많다.


유저프로세스가 알게 되면 트랜스포트 계층(L4)에서의 일은 트랜스포트 계층에서 해야할 일만 규정하고 그것의 간섭을 다른 레이어에서 불필요하게 할수 없게 하도록 하기 위해서 이다.


TCP의 상황이 어떤지를 알 수 있도록 제공이 되면(양 끝의 커널은 상당 부분 알게 된다, 중간 라우터에서 오류가 나더라도 ICMP메세지를 양 측 커널에 보내주기 때문에 커널은 에러 상황을 알 수 있다.) 좋겠다.


TCP 프로토콜 자체에서는 정의되지 않은 일이지만 커널이 상당부분 TCP의 현황에 대해서 알 수 있으니까 유닉스에서는 시스템콜의 형식으로 tcp상황을 유저 프로세스가 알 수 있도록 소켓 옵션을 제공 하기 시작했다. (처음부터 제공 한 것은 아니고 나중에 생긴것임)


생각 보다 종류가 많지만 몇가지만 살펴 보겠다.


응용 프로그램(유저프로세스,L5)에서 네트워크 계층(IP)의 서비스를 제공 받을 수 없다. 그래서 네트워크 상황이 어떤지 궁금하고 그것을 알게 되면 여러가지로 유저 프로그램에서 편리하게 사용할 수 있다.


TCP(L4)뿐만 아니라 ip(L3)까지 소켓 옵션으로 상태를 알 수 있게 도와준다.


소켓을 만들자 마자 소켓옵션을 설정해야 한다. 소켓에 옵션을 걸 수도 있고, 응용프로그램에서 어떤 소켓이 어떤 상태인지 알아 볼 수도있다.


위와 같은 두개의 함수로 소켓 옵션을 구해오거나, 셋팅 할 수 있다.


SO_BROADCAST 옵션 : TCP에서는 양측의 ip,port번호가 있어야 한다. TCP에서는 항상 1:1연결이 기본이므로 브로드 캐스팅이 불가하지만

UDP소켓은 가능하다. TCP에서 1000개의 연결에 똑같은 내용을 쓰려면 1000번 write 해야한다. 브로드 캐스팅은 데스티네이션 주소로 커널이 그 주소로 복제해서 보낸다. 여러 오버헤드가 빠지기 때문에 훨씬 빠르게 전송 된다.

이 소켓 옵션은 UDP에서만 가능하다. BROADCAST의 정의는 서브넷 내에 있는 UDP소켓을 사용하는 모든 녀석들에게 브로딩 캐스팅 해라이다.


서브넷이라는것은 라우팅 되지 않고 스윗칭 되는 네트워크 영역이다. 

서브넷 내에서만 브로드 캐스팅이 가능하다.브로드 캐스팅이 가능한 주소를 만들어 내는 방법이 있다.(IP주소를 네트워크주소와 호스트주소로 나눴을때 호스트 주소가 255? 일때 그 네트워크에 브로드 캐스팅 주소라고 기억함(?)) 

그 주소를 목적지 주소로 사용하는 경우에 그 네트워크에 있는 기계의 

커널이 그것을 허락하도록 되어 있으면 브로드 캐스팅 한다(UDP소켓에 대해서만)


UDP에서는 1:1 커넥션이라는것은 없지만 포트번호는 있고 상대방에게 브로드 캐스팅 할 수 있다. 하지만 브로드 캐스팅은 문제를 많이 일으킬 수 있기 때문에 상대 커널에서 그것을 허락하지 않는 경우도 있다.

-> 예를들어, 100개의 UDP데이터를 주고 받는다고 했을때(그 서브넷 내에서의 일) 계속해서 브로드 캐스팅을 하는 경우에 너무 패킷이 많아진다.

A->B 브로드 캐스팅 하고 B->A로 브로드 캐스팅하면서 무한루프 도는 경우도 발생할수 있기 때문에 이 옵션은 조심히 사용해야 한다.


SO_KEEPALIVE 옵션 : KEEPALIVE라는 이름 -> 살려둬라라는 뜻 같지만, 사실은 죽었는지 확인해서 확실히 죽여라 라는 의미이다.

TCP소켓에 해당하는 옵션이다. 이 소켓옵션을 가진 TCP소켓을 만든 클라이언트나 서버가(대부분 예전 서버에서 사용함)  서로와 2시간 동안 주고받은 데이터가 없는 경우 살아있냐라고 물어본다.


물어보는것은 probe라는 패킷을 보낸다(이것은 그냥 데이터 패킷인데 데이터 payload가 0이다.)이 probe는 peer가 반드시 응답해야 하는 TCP segment이다. 

이것을 받은 상대방이 살아 있으면 ack를 보낼 것이다.



1번 케이스 : 서버의 probe에 대해서 클라이언트가 정상적으로 응답하는 경우


2번 케이스 : 서버가 probe를 보냈으나 클라이언트 프로세스는 종료되고 기계는 살아있어서 리셋 메세지를 서버에게 보낸 경우

서버에서 read블락, -1리턴 되고 errno에 ECONNRESET설정


3번 케이스 : 서버가 probe를 보냈는데 응답이 없는 경우 -> 클라이언트 기계가 고장났거나 네트워크 상황이 안좋은경우

서버의 probe가 클라이언트 커널까지 도달하지 못해서 여러번의 재전송을 했음에도 불구하고 전달이 안된경우(여러개의 probe가 한개도 도달하지 못한경우)서버의 read블락에서 -1리턴되고 errno에 ETIMEDOUT설정된다.


probe를 재전송 중에 라우터로부터 ICMP메시지를 받은 경우 서버의 read블락에서 -1리턴 되고 errno에 EHOSTUNREACH가 설정된다.



여러가지 에러 케이스(중요,암기)


응용프로그램에서 Keep alive 소켓 옵션을 흉내 내기도 한다. 


SO_LINGER Socket Option : 소켓을 close 할까 말까


별도의 소켓 옵션이 설정 되어 있지 않으면 close를 호출시 바로 리턴된다. 커널이 reference count를 -1하고 그 값이 0이 된경우 FIN을 상대에게 보낸다. 위의 경우는 이미 이 경우가 발생했다고 치는것이다.


FIN과 data를 받은 서버는 piggybacking해서 data의 ack와 FIN을 되돌려 준다.


바쁜 서버가 나타나면서 이런 옵션들이 추가 되기 시작했다.

서버가 ack of data and FIN을 클라이언트를 보내고 나서 커널이 망가졌다고 하자.

클라이언트는 정상적으로 서버가 종료되었다고 생각 할 것이다. 이런경우에 SO_LINGER라는 옵션으로 이런 문제를 해결 하려고 했다.

근데 이 옵션으로도 잘 해결이 되지 않았다.


소켓에 SO_LINGER옵션을 설정한 경우 close를 호출했을때 일정시간동안 소켓을 없애지 않고 기다리게 할 수 있다.

기다리면서 정상적으로 tcp 연결이 half close되었는지 확인하는기 위한 옵션이 SO_LINGER이다(linger는 기다리다 라는 뜻이다)


클라이언트가 close를 호출했을때 블락상태로 머무른 상태에서 TCP 연결 종료가 정상적으로 되는지 안되는지 SO_LINGER옵션에 설정된 시간 만큼 검사하는것이다. 만약에 정해진 시간내에 연결이 종료 되지 않은 경우 클라이언트 커널이 미처 못보낸 데이터가 있더라도 그것을 그냥 모두 버려버리고 RESET메세지를 서버에게 보내게 된다.




 










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