네트워크 프로그래밍 09 소켓의 다양한 옵

zh025700·2022년 4월 13일
0

네트워크 프로그래밍


9. 소켓의 다양한 옵션

소켓의 다양한 옵션

소켓에는 다양한 특성들이 있다.

소켓 옵션 확인 (레발 안에 옵션이 있다!)

int getsockopt(int sock,int level,int optname, void* optval, socklen_t* optlen);
  • 성공시 0 실패시 -1 반환
  • sock: 확인할 소켓의 파일 디스크립터
  • level: 확인할 옵션의 프로토콜 레벨
  • optname: 확인할 옵션의 이름
  • optval: 확인 결과의 저장을 위한 버프의 주소값
  • optlen: optval로 전달된 주소 값의 버퍼 크기를 담고있는 변수의 주소값, optval을 통해 반환된 옵션 크기가 바이트 단위로 계산되어 저장

소켓 옵션 변경

int setsockopt(int sock,int level,int optname, const void* optval, socklen_t optlen);
  • 성공시 0 실패시 -1 반환
  • sock: 변경할 소켓의 파일 디스크립터
  • level: 변경할 옵션의 프로토콜 레벨
  • optname: 변경할 옵션의 이름
  • optval: 확인 결과의 저장을 위한 버프의 주소값
  • optlen: optval로 전달된 옵션정보의 바이트 단위로 크기 전달

Binary option

  • on off 가 가능하다. 옵션 테이블의 Flag가 있는 옵션이 binary option이고 없으면 아니다.
    • 0: off
    • 1: on
  • 설정하거나 평가할 수 있는 특정 값을 가져오고 반환하는 옵션

option 몇개

  • SO_TYPE

    • 소켓의 타입을 정수값으로 리턴
    • 확인만 가능하고 변경이 불가능한 옵션이다
      => 소켓의 타입은 소켓 생성시 결정되면 변경 불가!!
  • SO_RCVBUF & SO_SNDBUF

    • 소켓에 대한 입출력 버퍼에 관련
  • SO_REUSEADDR

    • 4개의 용도를 준다
      • 설정된 연결이 이 포트를 로컬 포트로 사용하는 경우에도, 서버가 잘 알려진 포트를 bind 할 수 있음
      • 각 인스턴스가 다른 로컬 IP 주소를 bind하는 한 와일드카드 주소에 bind된 기존 서버와 동일한 포트에서 새 서버를 시작할 수 있음.
      • 각 바인딩이 다른 로컬 IP 주소를 지정하는 한 단일 프로세스에서 동일한 포트를 여러 소켓에 바인딩할 수 있음
      • 완전히 중복된 바인딩 허용
  • TCP_MAXSEG

    • TCP 연결에 대한 MSS(데이터 조각 사이즈)를 확인하거나 설정할 수 있음
  • TCP_NODELAY

    • 기본값: 알고리즘 사용
    • 설정: TCP의 NAGLE 알고리즘을 끈다.

SO_SNDBUF & SO_RCVBUF

소켓이 생성되면 기본적으로 입력, 출력 버퍼가 생성된다.
  • SO_RCVBUF는 입력버퍼의 크기와 관련
  • SO_SNDBUF는 출력버퍼의 크기와 관련

이 둘을 이용해 버퍼의 크기를 참조, 변경이 가능

단 버퍼의 크기를 조정할때 원하는 크기대로 설정이 되지 않을 수도 있다.
이는 커널이 오버헤드를 막기위해 setsockopt를 할때 버퍼의 크기를 값의 두배로 설정하기 때문이다.

SO_REUSEADDR

시그널로 서버를 종료하고 다시 그 포트번호로 서버를 실행시키면 bind error가 발생한다. 그리고 3분후 다시 그 포트 번호로 서버를 실행하면 정상 동작한다.

Time wait 때문이다.

Time-wait

reliable 통신이 종료될때는 4-way handshaking을 거친다.
여기서 소켓은 바로 소멸되지 않고 Time-wait 상태를 일정시간 유지 후 소켓이 소멸이 된다.
(Time wait은 연결의 종료를 요청한(먼저 FIN메시지를 보낸) 호스트만 거침)

그래서 서버가 먼저 종료 요청을 보내면 해당 소켓이 Time-wait 후 소멸되기 때문에 해당 PORT 번호가 사용중인 것으로 나타나 bind error가 발생한다!!

서버나 클라이언트 모두 Time wait은 존재

그러나 클라이언트 소켓의 포트번호는 임의로 할당되기때문에(accpet) 때문에 time-wait에 대해 신경 쓰지 않아도 된다

왜 존재하나??

  • time-wait가 없다고 가정
    • 호스트 A가 B에게 마지막 ACK 메시지를 보냈지만 중간에 소멸되면??
      • B는 자신이 보낸 FIN 메시지를 A가 못받았을거라 생각하고 다시 보낸다.
    • 하지만,.. A소켓은 이미 소멸되었음 => B는 영원히 A의 ACK를 받지 못한다..

하지만!! time wait가 있따면!! 호스트 A가 다시 B로 ACK를 재전송을 하여 호스트 B는 정상 종료 할 수 있다.

주소의 재할당

그렇다면 갑작스럽게 서버가 종료가 되어서 Time-wait 때문에 포트 번호를 쓰지 못하는 상황에는 ?? 얼른 서비스를 구동해야하는데 몇 분을 기다린다면 매우 큰 문제가 될 수도 있다.

해결법

SO_REUSEADDR의 상태를 변경하면 된다!

적절한 변경을 통해 time wait 상태의 소켓에 할당되어 있는 port 번호를 새 소켓에 할당할 수 있다
  • SO_REUSEADDR의 디폴트 값: 0 = Time wait 상태의 소켓에 포트 번호는 할당이 불가함을 의미
  • 값:1이 되면 time wait 상태의 포트 번호가 새 소켓에 할당 가능

TCP_NODELAY

  • NAGLE 알고리즘의 목적
    • MSS보다 작은 크기의 패킷을 줄이기 위한 알고리즘
    • 네트워크에서 돌아다니는 패킷들의 넘침을 막기 위해

앞서 전송한 데이터에 대한 ACK 메시지를 받아야만 다음 데이터를 전송하는 알고리즘

  • on

    • 전에 보낸 데이터에 대한 ACK 메시지가 올때까지 버퍼에 다음에 보낼 메시지들이 들어온다
      • ACL가 도착하면 출력버퍼에 존재하는 데이터를 하나의 패킷으로 구성해 전송한다
  • off

    • 출력버퍼에 데이터가 전달되는 즉시 전송이 된다.
      => 네트워크 트래픽에 좋지 않다..

네트워크의 효율을 위해서는 NAGLE을 사용해야한다.

하지만 NAGLE이 항상 좋은것은 아님

NAGLE을 적용하지 않아도 트래픽 차이가 크지 않고 데이터의 전송이 빠른 경우도 있음
=> 용량이 큰 파일 데이터의 전송

필요하다면 NAGLE을 중지시켜야함

알고리즘은 적용하지 않아도 트래픽의 차이가 크지 않음 + NAGLE 적용보다 속도가 빠름
  • 방법
    • TCP_NODELAY를 1로 변경하면된다
setsockopt(sock,IPROTO_TCP,TCP_NODELAY,(void*)&opt_val,sizeof(opt_val));
profile
정리

0개의 댓글