int listen(int s, int backlog); 함수에서 backlog는 무엇인가요?
글쓴이: kkb / 작성시간: 수, 2010/04/07 - 7:57오후
int listen(int s, int backlog); 함수에서 backlog는 무엇인가요?
backlog가 클라이언트의 최대수라고 해서
listen(s, 10);
이와 같이 설정하면
최대 5개의 클라이언트가 접속할 수 있는지 알았는데
5개 이상의 클라이언트가 접속이 가능합니다.
여기저기 찾아보니
이미 연결된 클라이언트는 빼고
동시에 연결 요청 중인 클라이언트의 최대수라고 하기도 하는데
이 설명이 맞는지 궁금하고
맞다면 대부분의 경우 연결 요청 후 바로 연결이 이루어져서
동시에 연결 요청이 많이 일어나는 경우가 그렇게 많지 않을 거 같은데
이 숫자는 낮춰주는 것이 좋을까요?
높여주는 것이 좋을까요?
혹시 이 인자값이 DOS 공격을 대비해서 만들어 놓은 것 같은 생각이 들기도 하고...
아시는 분 답변주시면 감사하겠습니다
Forums:
backlog는 socket backlog와
backlog는 socket backlog와 kernel backlog가 있습니다. 알아보신 대로, 연결이 완료된 (ESTABLISHED) 소켓은 backlog에서 빠지게 됩니다.
DoS와 backlog의 관계는 DoS에 대비해서 backlog가 있는 것이 아니라, synflood attack 같은 Dos attack이 이 backlog를 꽉 채워서 더이상 연결을 받지 못하도록 하기 때문에 backlog 크기를 늘려 주라고 하는 것입니다.
kernel backlog는 tcp three-handshake 과정이 완료되기 전 까지를 처리를 하며, socket backlog는 그 이후 accept 되기 전까지의 socket을 관리하므로 (추정입니다. 누가 정확히 아시는 분 있으면 리플 부탁 드립니다) kernel backlog 처럼 큰 값을 가지지 않아도 무방합니다. 또한 자료형이 int 이지만 kernel backlog 보다 큰 값을 사용할 수 없습니다.
해당 값은 대략 5-16 정도 사이의 값을 많이 사용한다고 검색이 되는데, lighttpd의 경우 1024 (128 * 8)로 잡고 있고, apache 1.3의 경우 511(참 이해가 안되는 기본값입니다. ^^)로 잡혀 있고 빌드시에 이 값을 변경할 수 있습니다.
요즘 linux 배포본의 kernel tcp backlog 기본값은 대게 1024 입니다. 예전 2.2 또는 2.4 초반 시절(ram 크기가 크지 않던 시절..)에는 128이 기본값 이었습니다.
정확히 아는것은 아니고 저도 추정입니다. 백로그 :
정확히 아는것은 아니고 저도 추정입니다.
백로그 : 실제 데이타의 포인터를 값으로 가지는 카운터로 수신시만 관계하며 송신시는 버퍼 크기가 관여합니다
커널백로그의 경우 sk_buff 가 하나 만들어지면 +1 없어지면 -1 하고 전송 백로그의 경우 sock 이 같이 동작하는데
sk_buff 는 패킷 하나하나마다 무조건 구조체가 만들어지므로 +1 씩 됩니다만 sock 는 전송계층으로 올라왔을 때 +1 됩니다.
ICMP,AoE,ARP 처럼 전송으로 올라가지 않고 처리되는 부분은 sock 이 +1 되지 않으므로 이 2가지는 다릅니다.
DMA버퍼안의 수신된 패킷 하나가 실제로 없어졌을 때이며
IP단에서 처리해버리고 끝나는 경우는 sk_buff 가 없어지고 끝납니다만
전송계층까지 올라온 것의 경우 이 패킷이 listen() 을 호출한 프로세서가 점유한 사용자공간의 윈도우버퍼로 복사가 완전히 끝나야만 됩니다.이 때 관련 sk_buff 와 함께 sock 도 없어지며 backlog 도 줄어듭니다.
수치가 크다면 결국 덤프되지 못하고 정체된 블럭이 많다는 소리며 거기에는 어떤 문제가 있다는 말이며 대개 응용프로그램 로직 또는 디스크I/O 입니다.
커널 백로그 : NIC 이 DMA 을 통해 메모리에 데이타를 MTU 보다 작은 하나의 패킷으로 복사하는데 이 인트럽트가 감지될 때마다 커널은 sk_buff 를 만들고 패킷 하나의 주소를 포인터하고 백로그에 저장
MTU=1500 인 일반 경우 훨씬 더 많이 저장할 수 있죠.
디폴트값이 300 이고 300이 다 차면 랜카드는 블락되며 0 이 될 때까지(DMA 버퍼가 비워질 때까지)랜카드는 상대에게 PAUSE 전압을 보내게 되어 수신이 되지 않습니다.
300은 충분히 큽니다.문제가 된다면 다른 쪽을 찾아야겠지요.
전송백로그 : listen()을 호출한 프로그램 별로 있는데 그 총합은 디폴트 128 을 넘을 수 없습니다.
즉 아파치를 128 로 주어서 띄운다면 어디선가 이 웹서버로 접속이 오면 backlog +1 되고(이미 sock하나가 생기므로)SYN-ACK-ACK 관계가 동작하며 정상 확립되면 DMA 안의 데이타를 아파치 공간으로 덤프하는데 웹서버에는 이게 데이타 자체가 헤더가 대부분이므로
SYN 갯수와 backlog 가 1:1 관계처럼 보이지만
예를 들어 HTTP로 파일 업을 구현하면 SYN 하나에 sock 는 파일 전송 끝날 때까지 매 패킷 갯수마다 생기고
아파치 수신버퍼에서 디스크로 빨리빨리 저장하지 못하면 backlog 는 계속 늘어납니다.
역으로 보면 SYN 50 개에 backlog 60 개 정도 된다면 정상이라 할 수 있지만 SYN 50 개인데 백로그 1024 다...
그러면 플밍 로직에 문제 있거나 I/O 에 문제 있다는 소리므로
백로그 128 은 어이없는 값이 아닙니다.
그러나 웹서버의 경우
SYN 플러딩을 제외하고는 SYN 갯수가 클라이언트 갯수를 의미하니까 1024 를 잡아놓으면 1:1 을 가정하면 합리적이란 거죠
제 블로그에 이런 들을 쓰고 있습니다만 광고가 되니깐 네이버에서 찾아보시기 바랍니다.
listen() 함수에서 backlog는
일반적인 connection의 setup은 client가 connect()를 사용하여 connection request를 전송하면 server는 accept()를 사용하여 connection을 받아들입니다. 그런데 만약 server가 다른 작업을 진행 중이면 accept()를 할 수 없는 경우가 발생하고 이 경우 connection request는 queue에서 대기하는데 backlog는 이와 같이 accept() 없이 대기 가능한 connection request의 최대 개수입니다. 보통 5정도의 value를 사용하며 만약 아주 큰 값을 사용하면 kernel의 resource를 소모합니다.
따라서, 접속 가능한 클라이언트의 최대수가 아닌
연결을 기다리는 클라이언트의 최대수입니다
출처: 개발자를 위한 IPv6 전환 실무교육 (KISA 교육자료)
댓글 달기