- Today
- Total
Byeo
accept system call 0 - Intro 본문
일반적인 BSD Socket API는 server가 socket을 생성하고 bind 하고 listen 하면, 그다음은 accept을 수행합니다. 이 accept은 client가 연결 요청을 시도 함으로 인해 listen queue에 차있는 established packet을 꺼내온 뒤, socket()으로 생성했던 fd와는 다른 새로운 fd(!)를 생성하여 userspace에 제공합니다.
accept에서 확인해야 할 점은 다음과 같습니다.
1. TCP Passive open 3-way handshake 수행 지점:
server의 3-way handshake (SYN | ACK 반환)는 listen이 하는 것도 아니고, accept이 하는 것도 아닙니다.
- (1) Kernel이 SYN packet을 받으면
- (2) listen을 하는지 확인하고
- (3) listen의 backlog가 차지 않았다면
- (4) SYN | ACK을 반환한 뒤
- (5) accept이 호출될 때 userspace로 fd를 생성해 주는 구조입니다.
즉, accept이 호출될 때 SYN | ACK을 반환하는 것이 아닙니다. 코드에 listen만 작성하고 accept을 작성하지 않아도 TCP 3-way handshake가 이뤄지는지만 간단히 확인해 보면 알 수 있겠죠!
Server code (bklee-qemu):
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("fd value: %d, errno: %d\n", fd, errno);
struct sockaddr_in address;
address.sin_family = AF_INET;
//address.sin_addr.s_addr = INADDR_ANY;
address.sin_addr.s_addr = inet_addr("10.0.0.20");
address.sin_port = htons(8080);
int ret = bind(fd, (struct sockaddr *) &address, sizeof(address));
printf("bind return value: %d\n", ret);
ret = listen(fd, 5);
printf("listen return value: %d\n", ret);
sleep(1000);
}
그렇습니다! 3-way handshake는 kernel 내부에서 실행되는 과정이며, user application의 socket API와 관련이 없습니다.
2. Blocking Operation 원리:
socket option으로 O_NONBLOCK을 준 적이 없는 한, Accept은 blocking call입니다. client의 요청이 없었다면 accept system call은 return을 하지 않죠.
처음으로 마주하는 이 blocking call이 kernel 내부적에서 어떻게 구현됐는지 개인적으로 가장 궁금한 내용입니다.
그래서 아마 연재 순서로 (1) accept system call을 분석하는 포스트 다음으로 이어서 (2) SYN packet을 처리하고 TCP STATE가 TCP_SYN_REVD로 바뀌는 과정을 다루게 될 것 같습니다.
먼저 코드 스캔을 간단히 해봤는데요, accept system call 분석만으로도 꽤나 상당량을 차지할 것 같습니다.
'프로그래밍 (Programming) > 네트워크 스택' 카테고리의 다른 글
accept system call 2 (inet_csk_accept) (0) | 2024.05.15 |
---|---|
accept system call 1 (__sys_accept4) (0) | 2024.05.14 |
listen system call 3 (inet_hash) (0) | 2024.05.12 |
listen system call 2 (inet_listen) (0) | 2024.05.11 |
listen system call 1 (__sys_listen) (0) | 2024.05.11 |