CS/๋„คํŠธ์›Œํฌ

์†Œ์ผ“ ๋’ท์กฐ์‚ฌ์ข€ ํ•ด๋ดค์Šต๋‹ˆ๋‹ค

Une. 2025. 6. 4. 02:31

: ๊ฐœ๋ฐœ์ž๊ฐ€ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ถ”์ƒํ™”๋œ, ํŒŒ์ผ ์œ ์‚ฌ API๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ปค๋„์˜ ํ†ต์‹  ์ฑ„๋„ ๊ฐ์ฒด
(ํฌ์ŠคํŒ… ๋‚ด ๋Œ€๋ถ€๋ถ„์˜ ์ปค๋„ ์ฝ”๋“œ๋Š” Darwin XNU API๋กœ ๊ธฐ์ˆ ํ–ˆ์Šต๋‹ˆ๋‹ค.)

์™œ ํ•„์š”ํ•œ๊ฐ€?

  • ํ”„๋กœ์„ธ์Šค๋Š” ์ง์ ‘ ๋„คํŠธ์›Œํฌ ์žฅ์น˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Œ. ์ปค๋„๋งŒ์ด ์žฅ์น˜์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์Œ
  • ๋”ฐ๋ผ์„œ, ์‚ฌ์šฉ์ž ํ”„๋กœ์„ธ์Šค๋Š” ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋‹ค๋ฅธ ์ปดํ“จํ„ฐ์™€ ํ†ต์‹ ํ•˜๋ ค๋ฉด ์ปค๋„์—๊ฒŒ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋Š” API๊ฐ€ ํ•„์š”.
    ์ด๋•Œ ์ปค๋„๊ณผ ์†Œํ†ตํ•˜๋Š” ์ฐฝ๊ตฌ๊ฐ€ ์†Œ์ผ“

์ฆ‰, ์†Œ์ผ“์€ “์‚ฌ์šฉ์ž ํ”„๋กœ์„ธ์Šค์™€ ์ปค๋„ ๋„คํŠธ์›Œํฌ ์Šคํƒ ์‚ฌ์ด์˜ ๊ณ„์•ฝ๋œ ์ธํ„ฐํŽ˜์ด์Šค

์†Œ์ผ“์€ ๋„คํŠธ์›Œํฌ๋ฅผ ์ถ”์ƒ์ ์œผ๋กœ ์ด์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฐ์ฒด์ด๋ฉฐ, ์‹ค์งˆ์ ์ธ ๋…ธ๋“œ ์•ˆ์˜ ์ข…๋‹จ์ ์ด๋‹ค.
์œ„ ๊ทธ๋ฆผ์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ, ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋Š” ์†Œ์ผ“์„ ํ†ตํ•ด ๋งˆ์น˜ ์ง์ ‘ ์—ฐ๊ฒฐ๋œ ๊ฒƒ ์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
์ฆ‰, ์–‘ ์ข…๋‹จ์˜ ์†Œ์ผ“์€ “ํ†ต์‹  ์ฑ„๋„“์ด๊ธฐ๋„ ํ•˜๋‹ค.

๊ฐ์ฒด๋กœ์จ์˜ ์†Œ์ผ“

์†Œ์ผ“์€ ์ปค๋„์— ์กด์žฌํ•˜๋Š” ๊ฐ์ฒด, ์ปค๋„ ๋ฆฌ์†Œ์Šค์ด๋‹ค.
์†Œ์ผ“ ์กฐ์ž‘์€ ๋Œ€๋ถ€๋ถ„์˜ ์ปค๋„์—์„œ ํŒŒ์ผ ์กฐ์ž‘API์™€ ์œ ์‚ฌํ•œ API๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์†Œ์ผ“์€ ๊ฐ์ฒด์ด๋ฉฐ, ์ปค๋„์€ FileDiscriptor๋ฅผ ์ œ๊ณตํ•ด ์†Œ์ผ“์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ํ•  ๋ฟ์ด๋‹ค.
(์ด๋ฅผ ๋‘๊ณ  ๊ฐ€์ƒ ํŒŒ์ผ์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.)

๋„๊ตฌ๋กœ์จ์˜ Socket

๊ทธ๋Ÿฌ๋‚˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ž…์žฅ์—์„œ๋„, ์šด์˜์ฒด์ œ์˜ ์ž…์žฅ์—์„œ๋„ ์†Œ์ผ“์€ ํŒŒ์ผ์ด๋‹ค.

OS๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—๊ฒŒ ํŒŒ์ผ ์กฐ์ž‘์„ ์œ„ํ•œ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์™€ ์†Œ์ผ“ ๋””์Šคํฌ๋ฆฝํ„ฐ๋Š” ๊ฐ™์€ ๋””์Šคํฌ๋ฆฝํ„ฐ ํ…Œ์ด๋ธ” ๋‚ด์— ์กด์žฌํ•œ๋‹ค.
์†Œ์ผ“ ์ƒ์„ฑ ์‹œ์Šคํ…œ ์ฝœ์€ ์ด ๋””์Šคํฌ๋ฆฝํ„ฐ ํ…Œ์ด๋ธ” ๋‚ด์˜ ํŠน์ •ํ•œ ์ธ๋ฑ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ธ ํ•ด๋‹น ์ธ๋ฑ์Šค๋กœ ์†Œ์ผ“API๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
๊ทธ๋ž˜์„œ ์†Œ์ผ“์€ ํŒŒ์ผ์ด ์•„๋‹ˆ์ง€๋งŒ, ์šด์˜์ฒด์ œ๋Š” ์†Œ์ผ“์„ ํŠน์ˆ˜ํ•œ ํŒŒ์ผ๋กœ์จ ์ทจ๊ธ‰ํ•œ๋‹ค.

HTTP์˜ ์ˆ˜ํ–‰๋น„์„œ

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋„คํŠธ์›Œํฌ ํ†ต์‹  ์‹œ ๋ณต์ˆ˜๊ฐœ์˜ HTTP ๋ฉ”์„ธ์ง€๋ฅผ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์†ก์ˆ˜์‹ ํ•œ๋‹ค.
์ด๋•Œ, ๋ณ‘๋ ฌ์ ์ธ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ์œ„ํ•ด์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์†Œ์ผ“์„ ์‚ฌ์šฉํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ ๋งŽ์€ ์–‘์˜ ์†Œ์ผ“์€ OS์˜ ์ž…์žฅ์—์„œ ๊ฐœ๋ณ„์ ์ด๋‹ค.


HTTP๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ๋ฒจ์˜ ํ”„๋กœํ† ์ฝœ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์‹ค์งˆ์ ์ธ ์ „์†ก์„ ์œ„ํ•ด ๋” ํ•˜์œ„ ๋ ˆ์ด์–ด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
HTTP ๋ฉ”์„ธ์ง•์˜ ์ผ๊พผ์ด ๊ผญ ์†Œ์ผ“์ผ ํ•„์š”๋Š” ์—†๋‹ค. ์†Œ์ผ“์€ ๋‹จ์ง€ ์ „์†ก ๊ณ„์ธต์— ์ผ์„ ์‹œํ‚ค๊ธฐ ์œ„ํ•œ ์ฐฝ๊ตฌ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
HTTP๋Š” ์ „์†ก๊ณ„์ธต์œผ๋กœ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ด์•ผ ํ•  ๋ฟ์ด๊ณ , ์ด๋Š” ์†Œ์ผ“์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๊ฐ€์žฅ ๋ณดํŽธ์ ์ผ ๋ฟ์ด๋‹ค.
์ฆ‰, ์ „์†ก ๊ณ„์ธต์— ์ผ์„ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๋ฉด ์†Œ์ผ“์ด ์•„๋‹ˆ๋”๋ผ๋„ ์ƒ๊ด€ ์—†๋‹ค.

๋ถ„๋ฅ˜์™€ ๊ตฌ์„ฑ์š”์†Œ

(์•Œ๊ณ  ๊ณ„์…จ๋‚˜์š”? TCP/UDP๋Š” ์†Œ์ผ“๋ณด๋‹ค ๋จผ์ € ๊ณ ์•ˆ๋˜์—ˆ๋‹ต๋‹ˆ๋‹ค!)

๋ถ„๋ฅ˜

๊ฐ™์€ ์†Œ์ผ“์ผ์ง€๋ผ๋„ ๋‘ ๋ถ„๋ฅ˜๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

  • ์–ด๋–ค ๋„๋ฉ”์ธ์„ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€
  • ์–ด๋–ค ํƒ€์ž…์ธ๊ฐ€
    ์‹ค์งˆ์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ๋งํ•˜๋Š” ์†Œ์ผ“์˜ ๊ตฌ๋ถ„(์ŠคํŠธ๋ฆผ, ๋ฐ์ดํ„ฐ๊ทธ๋žจ ์†Œ์ผ“)์€ ํƒ€์ž…์œผ๋กœ์จ์˜ ๊ตฌ๋ถ„์„ ์ด์•ผ๊ธฐํ•œ๋‹ค.

๋„๋ฉ”์ธ ๊ธฐ์ค€

๋„๋ฉ”์ธ; ์ปค๋„ ๋‚ด๋ถ€์—์„œ ์ฃผ์†Œ ์ฒด๊ณ„๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋‹จ์œ„

  • ์ปค๋„ ๋„คํŠธ์›Œํฌ ์Šคํƒ์—์„œ๋Š” ์ฃผ์†Œ ์ฒด๊ณ„(AF_INET, AF_INET6, AF_UNIX, etc) ๋ณ„๋กœ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ํ”„๋กœํ† ์ฝœ ์ง‘ํ•ฉ(TCP, UDP, etc) ์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์ด ์ฃผ์†Œ ์ฒด๊ณ„ ํ•˜๋‚˜ํ•˜๋‚˜๋ฅผ "๋„๋ฉ”์ธ(domain)" ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
๋„๋ฉ”์ธ (Domain) ์„ค๋ช…
AF_INET IPv4 ์ธํ„ฐ๋„ท ํ”„๋กœํ† ์ฝœ
AF_INET6 IPv6 ์ธํ„ฐ๋„ท ํ”„๋กœํ† ์ฝœ
AF_UNIX ๋˜๋Š” AF_LOCAL ๋กœ์ปฌ IPC (ํŒŒ์ผ ๊ธฐ๋ฐ˜ ํ†ต์‹ )
AF_PACKET ๋ฆฌ๋ˆ…์Šค ์ „์šฉ. ์ด๋”๋„ท ํ”„๋ ˆ์ž„ ์ง์ ‘ ์†ก์ˆ˜์‹  (RAW ๋ ˆ๋ฒจ)
AF_NETLINK ์ปค๋„๊ณผ ์œ ์ €์ŠคํŽ˜์ด์Šค ๊ฐ„ ๋ฉ”์‹œ์ง€ ํ†ต์‹  (๋ฆฌ๋ˆ…์Šค)
AF_BLUETOOTH ๋ธ”๋ฃจํˆฌ์Šค ํ†ต์‹ 
AF_CAN Controller Area Network (์ž๋™์ฐจ)
AF_X25, AF_DECnet, ... ์˜ค๋ž˜๋œ ๋˜๋Š” ํŠน์ˆ˜ํ•œ ๋„คํŠธ์›Œํฌ ํ”„๋กœํ† ์ฝœ

ํƒ€์ž… ๊ธฐ์ค€

ํƒ€์ž… (Type) ์„ค๋ช…
SOCK_STREAM ์—ฐ๊ฒฐ์ง€ํ–ฅ ์ŠคํŠธ๋ฆผ ์†Œ์ผ“ (TCP์™€ ๋งค์นญ๋จ)
SOCK_DGRAM ๋น„์—ฐ๊ฒฐํ˜• ๋ฐ์ดํ„ฐ๊ทธ๋žจ ์†Œ์ผ“ (UDP์™€ ๋งค์นญ๋จ)
SOCK_RAW IP ํŒจํ‚ท์„ ์ง์ ‘ ๋‹ค๋ฃธ (ICMP, ์‚ฌ์šฉ์ž ์ง€์ • ํ”„๋กœํ† ์ฝœ ๋“ฑ)
SOCK_SEQPACKET ์—ฐ๊ฒฐ์ง€ํ–ฅ + ๋ฉ”์‹œ์ง€ ๊ฒฝ๊ณ„ ๋ณด์กด (ex. SCTP, UNIX ๋„๋ฉ”์ธ)
SOCK_RDM ์ˆœ์„œ ๋ณด์žฅ ๋น„์—ฐ๊ฒฐํ˜• ์†Œ์ผ“ (๊ฑฐ์˜ ์•ˆ ์“ฐ์ž„)

 

์†Œ์ผ“ 5-ํŠœํ”Œ; 

  • ํ”„๋กœํ† ์ฝœ; ์†Œ์ผ“ ํƒ€์ž…
  • ๋กœ์ปฌ IP ์ฃผ์†Œ
  • ๋กœ์ปฌ ํฌํŠธ ๋ฒˆํ˜ธ
  • ์›๊ฒฉ IP์ฃผ์†Œ
  • ์›๊ฒฉ ํฌํŠธ ๋ฒˆํ˜ธ

๋‹ค์Œ์€ Darwin XNU(์ปค๋„)์—์„œ ์†Œ์ผ“์˜ ๊ตฌํ˜„์ฒด์™€ ๋Œ€๋žต์ ์ธ ๊ณ„์ธต ๊ตฌ์กฐ ๋ฐ ์ƒ์„ฑ ์‹œ๋‚˜๋ฆฌ์˜ค ์ƒ˜ํ”Œ ์ฝ”๋“œ์ด๋‹ค.

// XNU: bsd/sys/socketvar.h
struct socket {
    short       so_type;      // SOCK_STREAM, SOCK_DGRAM ๋“ฑ
    int         so_options;
    short       so_state;
    void       *so_pcb;       // ํ”„๋กœํ† ์ฝœ ์ œ์–ด ๋ธ”๋ก (e.g., TCP/UDP ์ƒํƒœ)
    struct protosw *so_proto; // ์‚ฌ์šฉ ์ค‘์ธ ํ”„๋กœํ† ์ฝœ ํ•จ์ˆ˜ ํ…Œ์ด๋ธ”
    ...
};

// ์†Œ์ผ“์ด ์—ฐ๊ฒฐ๋  ์›๊ฒฉ์ง€ ์ฃผ์†Œ
struct sockaddr {
    __uint8_t   sa_len;       // ๊ตฌ์กฐ์ฒด ๊ธธ์ด
    sa_family_t sa_family;    // AF_INET, AF_INET6, AF_UNIX ๋“ฑ
    char        sa_data[14];  // ์ฃผ์†Œ์™€ ํฌํŠธ๋ฅผ ๋‹ด๋Š” ๋ฐ์ดํ„ฐ
};
// IPv4์ธ ๊ฒฝ์šฐ
struct sockaddr_in {
    __uint8_t       sin_len;      // ๊ตฌ์กฐ์ฒด ๊ธธ์ด
    sa_family_t     sin_family;   // AF_INET
    in_port_t       sin_port;     // ํฌํŠธ ๋ฒˆํ˜ธ (network byte order)
    struct in_addr  sin_addr;     // IPv4 ์ฃผ์†Œ
    char            sin_zero[8];  // ํŒจ๋”ฉ
};

User space: 
// sockfd == ๋””์Šคํฌ๋ฆฝํ„ฐ ํ…Œ์ด๋ธ” ๋‚ด์˜ File ๊ตฌ์กฐ์ฒด์˜ ์ธ๋ฑ์Šค
int sockfd = socket(AF_INET, SOCK_STREAM, 0);  ← ์†Œ์ผ“ ์ƒ์„ฑ ์‹œ์Šคํ…œ ์ฝœ, 
{   // socket๋ฅผ ์ƒ์„ฑํ•˜๋ฉด...
    // ๋Œ€๋žต์ ์ธ ํ๋ฆ„ (XNU ๊ธฐ์ค€)
    // ํŒŒ์ผ ๊ตฌ์กฐ์ฒด ์ƒ์„ฑ
    fd = alloc_fd();  // ์‚ฌ์šฉ์ž์—๊ฒŒ ์ค„ int sockfd, ํŒŒ์ผ๋””์Šคํฌ๋ฆฝํ„ฐ ํ…Œ์ด๋ธ” ๋‚ด ์ธ๋ฑ์Šค
    file = file_alloc();
    file->f_ops = &socketops;
    file->f_data = struct socket * so;
    so = socket_create();  // ์‹ค์ œ๋กœ struct socket์„ ์ƒ์„ฑ
    โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    user: int sockfd (์ด ๊ฐ’์ด 3์ด๋ฉด)
    ↓
    ์ปค๋„: file descriptor table[3] → struct file
                             โ†˜๏ธŽ
                             f_data → struct socket
}

struct sockaddr_in addr = { ... };

connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));

  struct sockaddr_in (IPv4 ์ฃผ์†Œ)
       ↓ (์บ์ŠคํŒ…)
  struct sockaddr     (์ธํ„ฐํŽ˜์ด์Šค ์šฉ๋„)
       ↓
  bind(), connect(), sendto() ๋“ฑ ์‹œ์Šคํ…œ ์ฝœ ํ˜ธ์ถœ
       ↓
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Kernel space:

  struct socket      ←  ์‹œ์Šคํ…œ ์ฝœ์„ ํ†ตํ•ด ์ปค๋„์—์„œ ์ƒ์„ฑ๋จ
   โ””โ”€→ ๋‚ด๋ถ€์ ์œผ๋กœ struct sockaddr๋ฅผ ํ†ตํ•ด ์ฃผ์†Œ ์ •๋ณด๋ฅผ ๋‹ค๋ฃธ
            โ””โ”€→ struct sockaddr_in (IPv4)
       ↓
  so_pcb → struct inpcb (IPv4 ์ƒํƒœ ๊ด€๋ฆฌ)
       โ†˜๏ธŽ
     ์ฃผ์†Œ ์ •๋ณด๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ sockaddr_in์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฒ˜๋ฆฌ

์•„๋ž˜๋Š” TCP๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ŠคํŠธ๋ฆผ ์†Œ์ผ“์˜ ์ƒ์„ฑ๋ถ€ํ„ฐ ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ์ƒ˜ํ”Œ ์ฝ”๋“œ์ด๋‹ค.

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    const char *message = "hello, world";

    // 1. ์†Œ์ผ“ ์ƒ์„ฑ (TCP)
    // tcp์— ๋Œ€์‘ํ•˜๋Š” Stream ์†Œ์ผ“์ž„์„ ๋ช…์‹œ
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in my_addr;
    my_addr.sin_family = AF_INET;
    // ์›๊ฒฉ์ง€๋กœ๋ถ€ํ„ฐ ์†ก์‹ ๋ฐ›๋Š” ๋ฐ์ดํ„ฐ์˜ IP์ฃผ์†Œ๋ฅผ ์ œํ•œํ•˜์ง€ ์•Š๊ฒ ๋‹ค๊ณ  ์„ค์ •
    my_addr.sin_addr.s_addr = INADDR_ANY;
    // 5000๋ฒˆ ํฌํŠธ๋กœ ๋„์ฐฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์†ก์‹ ๋ฐ›๊ฒ ๋‹ค๊ณ  ์„ค์ •
    my_addr.sin_port = htons(5000);
    bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr));

    // 2. ์„œ๋ฒ„ ์ฃผ์†Œ ์„ค์ •
    memset(&server_addr, 0, sizeof(server_addr));
    // IPv4๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๊ณ  ์„ค์ •
    server_addr.sin_family = AF_INET;
    // ์›๊ฒฉ์ง€ ์†ก์‹  ํฌํŠธ๋ฅผ 12345๋กœ ์„ค์ •
    server_addr.sin_port = htons(12345);  // ์„œ๋ฒ„ ํฌํŠธ
    // ์›๊ฒฉ์ง€ IP์ฃผ์†Œ๋ฅผ 192...100์œผ๋กœ ์„ค์ •
    inet_pton(AF_INET, "192.168.1.100", &server_addr.sin_addr);

    // 3. ์„œ๋ฒ„์— ์—ฐ๊ฒฐ
    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect");
        close(sockfd);
        exit(1);
    }

    // 4. ๋ฐ์ดํ„ฐ ์ „์†ก
    ssize_t sent = send(sockfd, message, strlen(message), 0);
    if (sent < 0) {
        perror("send");
        close(sockfd);
        exit(1);
    }

    printf("๋ฉ”์‹œ์ง€ ์ „์†ก ์™„๋ฃŒ (%zd bytes)\n", sent);

    close(sockfd);
    return 0;
}

์—ฌ๊ธฐ๊นŒ์ง€๋งŒ ์•Œ๋ฉด ์†Œ์ผ“์ด ๋ฌด์—‡์ธ์ง€๋Š” ์ถฉ๋ถ„ํžˆ ์•Œ์•˜์œผ๋ฆฌ๋ผ ์ƒ๊ฐํ•œ๋‹ค.
์ด์ œ Swift์˜ Network ํ”„๋ ˆ์ž„์›Œํฌ ์ฝ”๋“œ๊ฐ€ ๋ญ˜ ํ•˜๋Š”์ง€ ๋ณด์ด๋Š”๊ฐ€? ์†Œ์ผ“ API์™€ ๋งค์šฐ ๋‹ฎ์•˜๋‹ค.

import Foundation
import Network

let host = NWEndpoint.Host("example.com")  // ์—ฐ๊ฒฐํ•  ์›๊ฒฉ์ง€ ํ˜ธ์ŠคํŠธ
let port = NWEndpoint.Port(integerLiteral: 12345) //์—ฐ๊ฒฐํ•  ์›๊ฒฉ์ง€ ํฌํŠธ
// ์ˆ˜์‹ ํ•  ํฌํŠธ์™€ IP๋Š” ์ž๋™ ์ง€์ •
let connection = NWConnection(host: host, port: port, using: .tcp)
let queue = DispatchQueue(label: "TCPConnectionQueue")

connection.stateUpdateHandler = { state in
    switch state {
    case .ready:
        print("์—ฐ๊ฒฐ ์™„๋ฃŒ")

        let message = "Hello from main.swift"
        let data = message.data(using: .utf8)!

        connection.send(content: data, completion: .contentProcessed({ sendError in
            if let error = sendError {
                print("์ „์†ก ์‹คํŒจ: \(error)")
                connection.cancel()
                return
            }
            print("์ „์†ก ์™„๋ฃŒ")

            // ์‘๋‹ต ์ˆ˜์‹  ์‹œ๋„
            connection.receive(minimumIncompleteLength: 1, maximumLength: 1024) { receivedData, _, isComplete, receiveError in
                if let data = receivedData, !data.isEmpty {
                    let text = String(decoding: data, as: UTF8.self)
                    print("์ˆ˜์‹ : \(text)")
                } else if let error = receiveError {
                    print("์ˆ˜์‹  ์˜ค๋ฅ˜: \(error)")
                } else {
                    print("๋ฐ์ดํ„ฐ ์—†์Œ or ์—ฐ๊ฒฐ ์ข…๋ฃŒ")
                }

                connection.cancel()
            }
        }))

    case .failed(let error):
        print("์—ฐ๊ฒฐ ์‹คํŒจ: \(error)")
    case .waiting(let error):
        print("์—ฐ๊ฒฐ ๋Œ€๊ธฐ ์ค‘: \(error)")
    case .cancelled:
        print("์—ฐ๊ฒฐ ์ทจ์†Œ๋จ")
    default:
        break
    }
}

connection.start(queue: queue)
RunLoop.current.run()

์ „์†ก๊ณ„์ธต๊ณผ์˜ ๋ฐ”์ธ๋”ฉ

์ด์ฏค ๋˜๋ฉด ๋ˆˆ์น˜ ๋น ๋ฅธ ์‚ฌ๋žŒ์€ ์–ด๋А์ •๋„ ์˜ˆ์ƒํ•˜๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค.
์†Œ์ผ“์€ ๋‹จ์ง€ ์ „์†ก ๊ณ„์ธต์„ ์ถ”์ƒ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” API์ด๋‹ค.
์†Œ์ผ“์€ ์ถ”์ƒ์ ์ธ ํƒ€์ž…๊ณผ, ํ”„๋กœํ† ์ฝœ์— ๋”ฐ๋ฅธ ๋‚ด๋ถ€ ๊ตฌ์ฒด ํƒ€์ž…์ด ๋‹ค๋ฅด๋ฉฐ
์ด๋ฏธ ์ƒ์„ฑ์‹œ์— “ํ”„๋กœํ† ์ฝœ์— ๋งž์ถฐ์ ธ์žˆ๋Š” ์ƒํƒœ“ ๋กœ ํƒœ์–ด๋‚˜๋ฉฐ, ์ ์ ˆํ•œ ํ”„๋กœํ† ์ฝœ์˜ ์ „์†ก๊ณ„์ธต๊ณผ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.
์ดํ›„ ์ปค๋„์€ ๋ฐ”์ธ๋”ฉ๋œ ์†Œ์ผ“์˜ ๋ฒ„ํผ๋ฅผ ์ „์†ก๊ณ„์ธต์˜ ์ถœ๋ ฅ ๋ฒ„ํผ๋กœ ๊ฐ€์ ธ์˜ค๊ณ , ์ „์†ก๊ณ„์ธต์˜ ๋™์ž‘์— ๋”ฐ๋ผ ๋ฐ”์ธ๋”ฉ๋œ ์†Œ์ผ“์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋“ฑ ์†Œ์ผ“์€ ์ปค๋„์˜ ์ „์†ก๊ณ„์ธต์— ์˜ํ•ด ์ขŒ์ง€์šฐ์ง€ ๋œ๋‹ค.
๋”ฐ๋ผ์„œ ์–ด๋–ค ์˜๋ฏธ๋กœ “์†Œ์ผ“์€ ์ „์†ก๊ณ„์ธต์˜ ๋ž˜ํผ” ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์†Œ์ผ“์„ ์ƒ์„ฑํ•˜๋ฉด ์ „์†ก๊ณ„์ธต๊ณผ ๋ฐ”์ธ๋”ฉ๋˜๋Š”๋ฐ, ์ด๋Š” TCP/UDP ์ดˆ๊ธฐํ™” ๋ฃจํ‹ด์„ ๋™๋ฐ˜ํ•œ๋‹ค.
์ด ์ดˆ๊ธฐํ™” ๋ฃจํ‹ด์—๋Š” ๊ฐ ์—ฐ๊ฒฐ์— ๋Œ€ํ•œ ์ •๋ณด(IP/ํฌํŠธ ์ •๋ณด, TCP์ƒํƒœ)๋ฅผ ์ €์žฅํ•  ์ž๋ฃŒ๊ตฌ์กฐ๋„ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

User space:
    socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
  ↓ 
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Kernel space:
  ๋„๋ฉ”์ธ ๋ฆฌ์ŠคํŠธ(domains)์—์„œ AF_INET ๊ฒ€์ƒ‰
    ↓
  AF_INET ๋„๋ฉ”์ธ์˜ protosw[] ๋ฐฐ์—ด ํƒ์ƒ‰
    ↓
  pr_type == SOCK_STREAM, pr_protocol == IPPROTO_TCP์— ํ•ด๋‹นํ•˜๋Š” protosw ์„ ํƒ
    ↓
  struct socket *so ์ƒ์„ฑ
    ↓
  select TCP's protosw
    ↓
  so->so_proto = &tcp_protosw (protosw ํฌ์ธํ„ฐ ์—ฐ๊ฒฐ)
    ↓
  tcp_protosw.pr_usrreqs->pru_attach() ํ˜ธ์ถœ
    ↓
  inpcb ํ• ๋‹น ๋ฐ ์ดˆ๊ธฐํ™” (so->so_pcb = inpcb)
    ↓
  tcpcb ํ• ๋‹น ๋ฐ ์ดˆ๊ธฐํ™” (inpcb->inp_ppcb = tcpcb)

์ฃผ์š” ์ž๋ฃŒ๊ตฌ์กฐ

struct protosw[]; ํ”„๋กœํ† ์ฝœ ์Šค์œ„์น˜ ํ…Œ์ด๋ธ” : ๋„๋ฉ”์ธ ๋‚ด ์—ฌ๋Ÿฌ ํ”„๋กœํ† ์ฝœ ๊ตฌํ˜„์„ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์™€ ํ•จ๊ป˜ ์ •์˜ํ•œ ๋ฐฐ์—ด

  • ์ปค๋„ ๋„คํŠธ์›Œํฌ ์Šคํƒ ๋‚ด์—์„œ ๊ฐ ํ”„๋กœํ† ์ฝœ ๊ตฌํ˜„์„ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ ํ…Œ์ด๋ธ”๋กœ ์—ฐ๊ฒฐํ•ด ์ฃผ๋Š” ์—ญํ• ์„ ํ•จ
    • pr_usrreqs์— ์ปค๋„ ๋„คํŠธ์›Œํฌ ์†Œ์ผ“ ์ธํ„ฐํŽ˜์ด์Šค ํ•จ์ˆ˜๋“ค์ด ์ง‘์•ฝ๋จ
      → bind(), connect(), send(), recv() ๋“ฑ ํ”„๋กœํ† ์ฝœ๋ณ„ ๊ตฌํ˜„์ฒด ์—ฐ๊ฒฐ
  • socket() ํ˜ธ์ถœ ์‹œ ์ด ๋ฐฐ์—ด์—์„œ ์˜ฌ๋ฐ”๋ฅธ ํ”„๋กœํ† ์ฝœ์„ ์„ ํƒํ•˜์—ฌ ์†Œ์ผ“์— ๋ฐ”์ธ๋”ฉํ•˜๊ณ , ์ดํ›„ ํ”„๋กœํ† ์ฝœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ ํ˜ธ์ถœ์˜ ์ถœ๋ฐœ์ ์ด ๋จ
struct protosw {
    short   pr_type;               // ์†Œ์ผ“ ํƒ€์ž… (SOCK_STREAM, SOCK_DGRAM ๋“ฑ)
    struct  domain *pr_domain;     // ๋„๋ฉ”์ธ (AF_INET, AF_UNIX ๋“ฑ)
    short   pr_protocol;           // ํ”„๋กœํ† ์ฝœ ๋ฒˆํ˜ธ (IPPROTO_TCP ๋“ฑ)
    short   pr_flags;              // ๋™์ž‘ ํ”Œ๋ž˜๊ทธ
  	void    *pr_ousrreq;           // ์†Œ์ผ“ API์˜ ๊ฐ ์š”์ฒญ์— ๋Œ€ํ•œ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ ์ง‘ํ•ฉ

    // ์ฃผ์š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋“ค
    int   (*pr_input)(...);        // ์ˆ˜์‹  ํŒจํ‚ท ์ฒ˜๋ฆฌ
    int   (*pr_output)(...);       // ์ „์†ก ํŒจํ‚ท ์ฒ˜๋ฆฌ
    void  (*pr_ctlinput)(...);     // ์ œ์–ด ์ž…๋ ฅ ์ฒ˜๋ฆฌ (์˜ˆ: ICMP ์—๋Ÿฌ)
    int   (*pr_ctloutput)(...);    // ์†Œ์ผ“ ์˜ต์…˜ ๋“ฑ ์ œ์–ด ์ถœ๋ ฅ ์ฒ˜๋ฆฌ
    void  (*pr_init)(void);        // ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜
    void  (*pr_fasttimo)(void);    // ๋น ๋ฅธ ํƒ€์ด๋จธ ํ•จ์ˆ˜ (200ms)
    void  (*pr_slowtimo)(void);    // ๋А๋ฆฐ ํƒ€์ด๋จธ ํ•จ์ˆ˜ (500ms)
    void  (*pr_drain)(void);       // ๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ• ์‹œ drain ์ฒ˜๋ฆฌ
    ...
};
struct pr_usrreqs {
    int (*pru_abort)(struct socket *);
    int (*pru_accept)(struct socket *, struct sockaddr **);
    int (*pru_attach)(struct socket *, int, struct thread *);
    int (*pru_bind)(struct socket *, struct sockaddr *, struct thread *);
    int (*pru_connect)(struct socket *, struct sockaddr *, struct thread *);
    int (*pru_disconnect)(struct socket *);
    int (*pru_listen)(struct socket *, struct thread *);
    int (*pru_rcvd)(struct socket *, int);
    int (*pru_send)(struct socket *, int, struct mbuf *,
                    struct sockaddr *, struct mbuf *, struct thread *);
    int (*pru_shutdown)(struct socket *);
    ...
};

struct domain: ์ฃผ์†Œ ์ฒด๊ณ„ ์ง‘ํ•ฉ, AF_INET, AF_INET6, ect...

  • ๋„คํŠธ์›Œํฌ ์ฃผ์†Œ ์ฒด๊ณ„(Address Family)๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ปค๋„ ๋‚ด ์ž๋ฃŒ๊ตฌ์กฐ
    (์˜ˆ: AF_INET (IPv4), AF_INET6 (IPv6), AF_UNIX (๋กœ์ปฌ IPC) ๋“ฑ)
  • ์ฃผ์†Œ ์ฒด๊ณ„๋ณ„ ํ”„๋กœํ† ์ฝœ๋“ค์˜ ๊ทธ๋ฃนํ™”์™€ ๊ด€๋ฆฌ ๋‹จ์œ„ ์ด๋ฉฐ, ๊ด€๋ฆฌ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    • ์ปค๋„ ๋„คํŠธ์›Œํฌ ์Šคํƒ์€ ์—ฌ๋Ÿฌ domain ๊ฐ์ฒด๋ฅผ ๋ฆฌ์ŠคํŠธ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.
    • ์†Œ์ผ“ ์ƒ์„ฑ ์‹œ ๋„๋ฉ”์ธ ๋ฒˆํ˜ธ(dom_family)๋กœ ์ ์ ˆํ•œ domain์„ ์ฐพ์•„๋‚ธ๋‹ค.
    • ๊ทธ ๋„๋ฉ”์ธ ๋‚ด์˜ protosw[] ๋ฐฐ์—ด์„ ํ†ตํ•ด ํ”„๋กœํ† ์ฝœ(TCP, UDP, ICMP ๋“ฑ) ๊ตฌํ˜„์„ ์ฐพ๋Š”๋‹ค.
struct domain {
    int dom_family;                 // ์ฃผ์†Œ ์ฒด๊ณ„ ๋ฒˆํ˜ธ (AF_INET, AF_UNIX ๋“ฑ)
    const char *dom_name;           // ๋„๋ฉ”์ธ ์ด๋ฆ„ ("internet", "unix" ๋“ฑ)
    struct protosw *dom_protosw;    // ํ•ด๋‹น ๋„๋ฉ”์ธ์˜ ํ”„๋กœํ† ์ฝœ ์Šค์œ„์น˜ ๋ฐฐ์—ด (ex: TCP, UDP)
    struct protosw *dom_protoswNPROTOSW; // ํ”„๋กœํ† ์ฝœ ์Šค์œ„์น˜ ๋ฐฐ์—ด ๋ ํฌ์ธํ„ฐ
    struct domain *dom_next;        // ์ปค๋„ ๋‚ด ๋„๋ฉ”์ธ ๋ฆฌ์ŠคํŠธ์—์„œ ๋‹ค์Œ ๋„๋ฉ”์ธ ํฌ์ธํ„ฐ
    ...
};
  • struct inpcb (Internet Protocol Control Block)
    • IP ๊ณ„์ธต ๊ด€๋ จ ์ •๋ณด ํฌํ•จ
    • ๋กœ์ปฌ IP, ์›๊ฒฉ IP, ํฌํŠธ ๋ฒˆํ˜ธ ์ €์žฅ
    • ์†Œ์ผ“ ํฌ์ธํ„ฐ ์—ญ์ฐธ์กฐ ๊ฐ€๋Šฅ
    • TCP, UDP ๋ชจ๋‘ ์ด ๊ณ„์ธต์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ
struct inpcb {
    struct socket *inp_socket;    // ์—ญ์ฐธ์กฐ ๊ฐ€๋Šฅํ•œ ์†Œ์ผ“
    struct in_addr inp_laddr;     // ๋กœ์ปฌ IP
    struct in_addr inp_faddr;     // ์›๊ฒฉ IP
    u_short inp_lport;            // ๋กœ์ปฌ ํฌํŠธ
    u_short inp_fport;            // ์›๊ฒฉ ํฌํŠธ
    void *inp_ppcb;               // ํ”„๋กœํ† ์ฝœ๋ณ„ PCB ํฌ์ธํ„ฐ (TCP: tcpcb)
    ...
};
  • struct tcpcb (TCP Control Block)
    • TCP ์—ฐ๊ฒฐ์˜ ์ƒํƒœ๋ฅผ ์ƒ์„ธํžˆ ๊ด€๋ฆฌ
    • TCP FSM ์ƒํƒœ, ์†ก์ˆ˜์‹  ์‹œํ€€์Šค ๋ฒˆํ˜ธ, ํƒ€์ด๋จธ ์ƒํƒœ ๋“ฑ ํฌํ•จ
struct tcpcb {
    struct inpcb *t_inpcb;    // ์ƒ์œ„ inpcb ์—ฐ๊ฒฐ
    int t_state;             // TCP ์—ฐ๊ฒฐ ์ƒํƒœ (SYN_SENT, ESTABLISHED ๋“ฑ)
    u_int32_t snd_una;       // ์†ก์‹ ์—์„œ ๋งˆ์ง€๋ง‰์œผ๋กœ ACK ๋ฐ›์€ ์‹œํ€€์Šค ๋ฒˆํ˜ธ
    u_int32_t snd_nxt;       // ๋‹ค์Œ ๋ณด๋‚ผ ์‹œํ€€์Šค ๋ฒˆํ˜ธ
    u_int32_t rcv_nxt;       // ๋‹ค์Œ ๋ฐ›์„ ์‹œํ€€์Šค ๋ฒˆํ˜ธ
    ...
};
Let's binding
  1. ์‚ฌ์šฉ์ž ํ˜ธ์ถœ
    • int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      • AF_INET : IPv4 ๋„๋ฉ”์ธ ์„ ํƒ
      • SOCK_STREAM : ์ŠคํŠธ๋ฆผ ํƒ€์ž… (TCP)
      • IPPROTO_TCP : TCP ํ”„๋กœํ† ์ฝœ ๋ช…์‹œ
  2. ์ปค๋„ ๋‚ด๋ถ€ ์ ˆ์ฐจ (sys_socket()socreate())
    • ์ปค๋„์€ domain[] ๋ฆฌ์ŠคํŠธ์—์„œ AF_INET ๋„๋ฉ”์ธ์„ ์ฐพ์Œ.
    • AF_INET ๋„๋ฉ”์ธ์˜ protosw[] ๋ฐฐ์—ด์„ ์ˆœํšŒํ•˜๋ฉด์„œ pr_type == SOCK_STREAM && pr_protocol == IPPROTO_TCP ์ธ ํ”„๋กœํ† ์ฝœ ์Šค์œ„์น˜ ์—”ํŠธ๋ฆฌ๋ฅผ ์ฐพ์Œ.
    • ์ด ์—”ํŠธ๋ฆฌ๋ฅผ ์„ ํƒํ•˜์—ฌ ์†Œ์ผ“์˜ so_proto ํ•„๋“œ์— ์—ฐ๊ฒฐ.
      • socket->so_proto = protosw_entry
  3. ํ”„๋กœํ† ์ฝœ ์ œ์–ด ๋ธ”๋ก(PCB) ์ƒ์„ฑ ๋ฐ ์—ฐ๊ฒฐ
    • ํ”„๋กœํ† ์ฝœ ์Šค์œ„์น˜ ๊ตฌ์กฐ์ฒด(protosw) ์•ˆ์˜ pr_usrreqs->pru_attach() ํ•จ์ˆ˜ ํ˜ธ์ถœ (TCP: tcp_attach()).
    • tcp_attach() ๋‚ด์—์„œ ๋‹ค์Œ์ด ์ˆ˜ํ–‰๋จ:
      1. struct inpcb ํ• ๋‹น ๋ฐ ์ดˆ๊ธฐํ™”
        IP ์ฃผ์†Œ ๋ฐ ํฌํŠธ ๋“ฑ ๋„คํŠธ์›Œํฌ ์‹๋ณ„์ž์šฉ ์ƒํƒœ ์ €์žฅ
      2. struct tcpcb ํ• ๋‹น ๋ฐ ์—ฐ๊ฒฐ
        TCP ์—ฐ๊ฒฐ ์ƒํƒœ(์ƒํƒœ ๋จธ์‹ , ์‹œํ€€์Šค ๋ฒˆํ˜ธ, ์œˆ๋„์šฐ ํฌ๊ธฐ ๋“ฑ) ์ €
    • struct socket์˜ so_pcb ํฌ์ธํ„ฐ๊ฐ€ inpcb๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  inpcb->inp_ppcb๊ฐ€ tcpcb๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ˜•ํƒœ๋กœ 2์ค‘ ํฌ์ธํ„ฐ ์—ฐ๊ฒฐ ๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑ

์ƒ๋ช…์ฃผ๊ธฐ

1. socket()   → struct socket ์ƒ์„ฑ + proto ์—ฐ๊ฒฐ
2. bind()     → ๋กœ์ปฌ ์ฃผ์†Œ ํ• ๋‹น
3. listen()   → passive open (์„œ๋ฒ„)
4. connect()  → active open (ํด๋ผ, SYN ์ „์†ก)
5. accept()   → ํด๋ผ ์—ฐ๊ฒฐ ์ˆ˜๋ฝ
6. read/write(send/recv)  → mbuf์„ ํ†ตํ•œ ์ž…์ถœ๋ ฅ
7. shutdown() → TCP FIN/FIN-ACK
8. close()    → ์ž์› ํ•ด์ œ, socket free
  1. ์†Œ์ผ“ ์ƒ์„ฑ (์†Œ์ผ“๊ณผ ์ „์†ก๊ณ„์ธต ๋ฐ”์ธ๋”ฉ)
    • ์œ ์ € ๊ณต๊ฐ„:
      int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    • ์ปค๋„ ๋‚ด๋ถ€:
      • socket() ์‹œ์Šคํ…œ ์ฝœ → sys_socket()
      • socreate() ํ˜ธ์ถœ:
        • ์ฃผ์†Œ ํŒจ๋ฐ€๋ฆฌ (e.g., AF_INET)
        • ํƒ€์ž… (e.g., SOCK_STREAM)
        • ํ”„๋กœํ† ์ฝœ (e.g., IPPROTO_TCP)
      • ๋‚ด๋ถ€์—์„œ ๋„๋ฉ”์ธ(domain, domain[])๊ณผ ํ”„๋กœํ† ์ฝœ ์Šค์œ„์น˜(protosw[])๋ฅผ ํƒ์ƒ‰
      • struct socket ๊ฐ์ฒด ์ƒ์„ฑ
      • ๊ด€๋ จ ํ”„๋กœํ† ์ฝœ ์ œ์–ด ๋ธ”๋ก (inpcb, tcpcb) ๋“ฑ๋„ ํ•จ๊ป˜ ํ• ๋‹น
  2. ์†Œ์ผ“ ๋ฐ”์ธ๋”ฉ (์„ ํƒ์ ) (์œ„์˜ ๋ฐ”์ธ๋”ฉ๊ณผ๋Š” ๋‹ค๋ฆ„)
    • ์œ ์ € ๊ณต๊ฐ„:
      bind(sockfd, ...);
    • ์ปค๋„ ๋‚ด๋ถ€:
      • sys_bind()sobind() → ํ”„๋กœํ† ์ฝœ ๋ ˆ๋ฒจ์˜ pr_bind() ํ˜ธ์ถœ
        • ์˜ˆ: TCP๋ผ๋ฉด tcp_usrreq()์—์„œ PRU_BIND ์ฒ˜๋ฆฌ
      • inpcb์— ๋กœ์ปฌ ์ฃผ์†Œ(port, IP) ์„ค์ •
  3. ์†Œ์ผ“ listen (์„œ๋ฒ„์˜ ๊ฒฝ์šฐ)
    • ์œ ์ € ๊ณต๊ฐ„:
      listen(sockfd, backlog);
    • ์ปค๋„ ๋‚ด๋ถ€:
      • sys_listen()solisten()
        • ํ”„๋กœํ† ์ฝœ์˜ pr_listen() ์ฒ˜๋ฆฌ (e.g., TCP์—์„œ passive open)
        • so_options์— SO_ACCEPTCONN ์„ค์ •
      • ๋ฐฑ๋กœ๊ทธ ํ ์ƒ์„ฑ
  4. ์†Œ์ผ“ ์—ฐ๊ฒฐ
    • ํด๋ผ์ด์–ธํŠธ:
      connect(sockfd, ...);
      • ์ปค๋„์—์„œ๋Š” soconnnect() ํ˜ธ์ถœ
      • ํ”„๋กœํ† ์ฝœ์˜ pr_connect() (e.g., TCP์˜ active open → SYN ์†ก์‹ )
      • TCP 3-way handshake ์‹œ์ž‘
    • ์„œ๋ฒ„:
      accept(sockfd, ...);
      • ์ปค๋„์—์„œ soaccept(), pr_accept() ํ˜ธ์ถœ
      • ์ƒˆ๋กœ์šด struct socket ์ƒ์„ฑ (connected socket)
      • ๊ธฐ์กด listen socket๊ณผ ๋ถ„๋ฆฌ๋œ ์ƒˆ๋กœ์šด ์—ฐ๊ฒฐ ์†Œ์ผ“ ๋ฐ˜ํ™˜
  5. ๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹ 
    • ์œ ์ € ๊ณต๊ฐ„:
      write(sockfd, buffer, len); // send
      read(sockfd, buffer, len); // recv
    • ์ปค๋„:
      • sosend() / soreceive() ํ˜ธ์ถœ
      • TCP: tcp_output() / tcp_input() → mbuf ๋‹จ์œ„๋กœ so_snd/so_rcv ํ์— ๋ถ™์Œ
      • ์ˆ˜์‹ ๋œ TCP ์„ธ๊ทธ๋จผํŠธ๋Š” mbuf๋กœ ๊ฐ์‹ธ์ ธ ์†Œ์ผ“ ์ˆ˜์‹  ๋ฒ„ํผ๋กœ ๋“ค์–ด์˜ด
  6. ์†Œ์ผ“ ์ข…๋ฃŒ (Shutdown/Close)
    • ์œ ์ € ๊ณต๊ฐ„:
      shutdown(sockfd, SHUT_RDWR); close(sockfd);
    • ์ปค๋„:
      • shutdown()์€ soshutdown()์„ ํ†ตํ•ด PRU_SHUTDOWN ์ฒ˜๋ฆฌ (TCP: FIN ์ „์†ก)
      • close()๋Š” soclose()๋ฅผ ํ˜ธ์ถœ:
        • ์—ฐ๊ฒฐ ์ข…๋ฃŒ ์ฒ˜๋ฆฌ (pr_disconnect)
        • ๋ฒ„ํผ ๋น„์›€
        • inpcb, tcpcb, mbuf ๋“ฑ ์†Œ์ผ“ ๋ฆฌ์†Œ์Šค ํ•ด์ œ

์›๊ฒฉ์ง€๋กœ ๋ฐ์ดํ„ฐ ์†ก์‹ 

[์œ ์ € write()]
    ↓
[sosend()]
    โ””โ”€> check sbspace()
    โ””โ”€> mbuf์— ๋ฐ์ดํ„ฐ ๋ณต์‚ฌ
    ↓
[tcp_usr_send()]
    ↓
[tcp_output()]
    โ””โ”€> TCP ํ—ค๋” + ๋ฐ์ดํ„ฐ ์ƒ์„ฑ
    ↓
[ip_output()]
    ↓
[if_output() → NIC]
    ↓
[์‹ค์ œ ์†ก์‹ ]

--- ์ดํ›„ ---
[ACK ์ˆ˜์‹ ]
    ↓
[tcp_ack_received()]
    ↓
[์†ก์‹  ๋ฒ„ํผ sb_cc ์ค„์–ด๋“ฆ]
    ↓
[sowwakeup()]
  1. ์œ ์ € ๊ณต๊ฐ„์—์„œ write() ํ˜ธ์ถœ
    • ์†Œ์ผ“์˜ ํ•จ์ˆ˜ sosend() → mbuf์— ๋ฐ์ดํ„ฐ ์ €์žฅ
  2. sosend() ํ˜ธ์ถœ → ์†Œ์ผ“ ๋ฒ„ํผ ํ™•์ธ ๋ฐ ๋ฐ์ดํ„ฐ ๋ณต์‚ฌ
    • so == struct socket — ์†Œ์ผ“ ์ „๋ฐ˜ ์ƒํƒœ
    • buf == struct sockbuf — ์†ก์‹  ๋ฒ„ํผ (so_snd)
    • ๋‚ด๋ถ€ ์ฒ˜๋ฆฌ:
    1. sbspace(&so->so_snd)๋กœ ์†ก์‹  ๋ฒ„ํผ์— ์—ฌ์œ  ์žˆ๋Š”์ง€ ํ™•์ธ
    2. ์—ฌ์œ  ์—†์œผ๋ฉด:
      • blocking ๋ชจ๋“œ๋ฉด: sbwait()๋กœ sleep → wakeup ๊ธฐ๋‹ค๋ฆผ
      • non-blocking ๋ชจ๋“œ๋ฉด: EWOULDBLOCK ๋ฐ˜ํ™˜
    3. ์—ฌ์œ  ์žˆ์œผ๋ฉด:
      • ์œ ์ €์˜ buf๋ฅผ mbuf ์ฒด์ธ์œผ๋กœ ๋ณต์‚ฌ
      • ์ด mbuf๋“ค์„ so->so_snd.sb_mb์— ์—ฐ๊ฒฐ
  3. ํ”„๋กœํ† ์ฝœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ ํ˜ธ์ถœ (TCP ๋ ˆ์ด์–ด ์ง„์ž…)
    • sosend()์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์—์„œ ์ด ์†Œ์ผ“์ด ๋ฐ”์ธ๋”ฉ๋œ ํ”„๋กœํ† ์ฝœ์˜ send ๋ฃจํ‹ด ํ˜ธ์ถœ:so -> so_proto -> pr_usrreqs -> pru_send()
      ์ด ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋Š” tcp_usr_send()๋กœ ์„ค์ •๋˜์–ด ์žˆ์Œ. ์ฆ‰:
      write() -> sosend() -> tcp_usr_send()
    • tcp_usr_send()`์˜ ์—ญํ• :
      • TCP ์—ฐ๊ฒฐ์ด ์ •์ƒ ์ƒํƒœ์ธ์ง€ ํ™•์ธ
      • ์†Œ์ผ“ ์†ก์‹  ๋ฒ„ํผ์˜ mbuf ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์Œ
      • tcp_output() ํ˜ธ์ถœํ•˜์—ฌ ์‹ค์งˆ์  ์†ก์‹  ์ˆ˜ํ–‰
    • tcp_usr_send()๊ฐ€ TCP ๊ณ„์ธต ์ง„์ž…์ 
      • → ๋‚ด๋ถ€์ ์œผ๋กœ ์ฆ‰์‹œ tcp_output() ํ˜ธ์ถœ
      • → TCP๋Š” ์†ก์‹  ๋ฒ„ํผ๋ฅผ ์ฐธ์กฐํ•ด ์„ธ๊ทธ๋จผํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , ๋ณด๋‚ด๊ธฐ ์‹œ์ž‘ํ•จ
  4. TCP ๊ณ„์ธต์—์„œ ์†ก์‹  ์„ธ๊ทธ๋จผํŠธ ์ƒ์„ฑ (tcp_output())
    • ์—ฌ๊ธฐ์„œ ๋“œ๋””์–ด TCP ํ—ค๋”๊ฐ€ ๋ถ™์€ ์„ธ๊ทธ๋จผํŠธ๊ฐ€ ์ƒ์„ฑ๋จ.
    • ์ฃผ์š” ์ฒ˜๋ฆฌ:
      1. tcp_output()์€ ์†Œ์ผ“์˜ so_snd.sb_mb์—์„œ mbuf ๋ฐ์ดํ„ฐ ์ฝ์Œ
      2. ์„ธ๊ทธ๋จผํŠธ ํฌ๊ธฐ ๊ณ„์‚ฐ (MSS ๊ณ ๋ ค)
      3. ํ•„์š”ํ•œ TCP ํ—ค๋” ์ƒ์„ฑ (SEQ ๋ฒˆํ˜ธ ๋“ฑ)
      4. ๋ฒ„ํผ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ m_copydata() ๋“ฑ์œผ๋กœ ์กฐ๋ฆฝ
      5. ํŒจํ‚ท์„ IP ๊ณ„์ธต์— ๋„˜๊น€: ip_output() ํ˜ธ์ถœ
  5. IP ๊ณ„์ธต → ์ธํ„ฐํŽ˜์ด์Šค ๋“œ๋ผ์ด๋ฒ„
    • ip_output()์€ ๋ผ์šฐํŒ… ํ…Œ์ด๋ธ”, MTU ํ™•์ธ, IP ํ—ค๋” ์ƒ์„ฑ
    • ์ดํ›„ if_output() ํ†ตํ•ด NIC ๋“œ๋ผ์ด๋ฒ„๋กœ ํŒจํ‚ท ์ „๋‹ฌ
    • ๋“œ๋ผ์ด๋ฒ„๊ฐ€ DMA ๋“ฑ์œผ๋กœ NIC์— ํŒจํ‚ท์„ ๋„˜๊ฒจ ์‹ค์ œ ์ „์†ก
  6. ์†ก์‹  ์™„๋ฃŒ ํ›„ ์ฒ˜๋ฆฌ
    • ํŒจํ‚ท์ด ์ „์†ก๋œ๋‹ค๊ณ  ํ•ด์„œ ๋ฐ”๋กœ ๋ฒ„ํผ์—์„œ ์ œ๊ฑฐ๋˜์ง„ ์•Š์Œ
    • TCP๋Š” ACK๋ฅผ ๋ฐ›์•„์•ผ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ์†ก์‹  ์™„๋ฃŒ๋˜์—ˆ๋‹ค๊ณ  ํŒ๋‹จ
      • -> TCP์˜ ์‹ ๋ขฐ์„ฑ ์žˆ๋Š” ์ „์†ก ๋ณด์žฅ, ACK๋ฅผ ์ „์†ก ์™„๋ฃŒ ๋กœ ๊ฐ„์ฃผ, ์†Œ์ผ“ ์†ก์‹  ๋ฒ„ํผ flush
    • ACK ์ˆ˜์‹  ์‹œ → tcp_ack_received()sbfree() ๋˜๋Š” sbflush() ํ˜ธ์ถœ
      • so_snd.sb_cc ๊ฐ์†Œ → ์—ฌ์œ  ๊ณต๊ฐ„ ์ƒ๊น€ → sowwakeup() ๋ฐœ์ƒ
      • select() ๋“ฑ์—์„œ writable๋กœ ๊ฐ์ง€๋จ

์›๊ฒฉ์ง€๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ์ˆ˜์‹ 

[ Network Driver (NIC) ]
        ↓
[ IP ๊ณ„์ธต ] ← (AF_INET ๋ฐ”์ธ๋”ฉ ๊ธฐ๋ฐ˜ demux)
        ↓
[ TCP ๊ณ„์ธต ] ← (inpcb lookup (dst ip, port) → tcpcb → ์†Œ์ผ“ ์—ฐ๊ฒฐ → ์กฐ๋ฆฝ)
        ↓
[ Socket ์ˆ˜์‹  ๋ฒ„ํผ(so_rcv.sb_mb) ] ← (TCP์˜ ์ˆ˜์‹  ๋ฐ์ดํ„ฐ๋ฅผ mbuf์— ๋‹ด์•„ ๋ฒ„ํผ์— append)
        ↓
[ ์œ ์ € ๊ณต๊ฐ„์—์„œ recv() / read() ๋กœ ์ฝ์Œ ]
  1. NIC → ์ปค๋„ ์ง„์ž… (Ethernet ์ˆ˜์‹ )
    • ๋„คํŠธ์›Œํฌ ์นด๋“œ(NIC)๊ฐ€ ์ธํ„ฐ๋ŸฝํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ํŒจํ‚ท์„ ์ปค๋„๋กœ ์ „๋‹ฌ
    • ์ปค๋„์˜ ๋“œ๋ผ์ด๋ฒ„ ๋ ˆ๋ฒจ์—์„œ ์ด๋”๋„ท ํ”„๋ ˆ์ž„ ์ˆ˜์‹  ์ฒ˜๋ฆฌ
    • ์ด๋”๋„ท ํ”„๋ ˆ์ž„์—์„œ EtherType(0x0800) → IPv4๋กœ ์‹๋ณ„๋จ
      `ether_input() → ip_input()``
  2. IP ๊ณ„์ธต ์ฒ˜๋ฆฌ
    • ip_input() ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์–ด IP ํ—ค๋”๋ฅผ ํŒŒ์‹ฑ
    • ๋ชฉ์ ์ง€ IP, TTL, ์ฒดํฌ์„ฌ, ํ”„๋กœํ† ์ฝœ(TCP=6), ์ด ๊ธธ์ด ๋“ฑ ํ™•์ธ
    • IP ๊ณ„์ธต์€ ์ƒ์œ„ ๊ณ„์ธต demux๋ฅผ ์œ„ํ•ด inetsw[] ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•จ
    • ์ด ๋ฐฐ์—ด์€ ๊ฐ ํ”„๋กœํ† ์ฝœ(TCP, UDP ๋“ฑ)์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ ๋ฃจํ‹ด์„ ๋“ฑ๋กํ•œ ๊ฒƒ
    • TCP์ธ ๊ฒฝ์šฐ inetsw[IPPROTO_TCP]tcp_input() ํ˜ธ์ถœ
      ip_input() → inetsw[IPPROTO_TCP].pr_input = tcp_input
  3. TCP ๊ณ„์ธต ์ฒ˜๋ฆฌ (tcp_input())
    • IP ํŽ˜์ด๋กœ๋“œ๋ฅผ TCP ์„ธ๊ทธ๋จผํŠธ๋กœ ํ•ด์„
      • TCP ํ—ค๋” ํŒŒ์‹ฑ (SEQ, ACK, ํ”Œ๋ž˜๊ทธ, ์ฒดํฌ์„ฌ, ์œˆ๋„์šฐ ๋“ฑ)
      • ํฌํŠธ ๋ฒˆํ˜ธ(16๋น„ํŠธ)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ปค๋„ ๋‚ด๋ถ€์˜ inpcb(ํ”„๋กœํ† ์ฝœ ์ œ์–ด ๋ธ”๋ก) ํƒ์ƒ‰
    • inpcb ํƒ์ƒ‰ (TCP ์†Œ์ผ“์— ๋ฐ”์ธ๋”ฉ๋œ ์ƒํƒœ ํ™•์ธ)
      • IP ์ฃผ์†Œ + ํฌํŠธ ๋ฒˆํ˜ธ 4์Œ์œผ๋กœ ๋งค์นญ๋˜๋Š” inpcb ๊ตฌ์กฐ์ฒด ์ฐพ๊ธฐ
      • inpcb๋Š” ๊ฒฐ๊ตญ tcpcb ๊ตฌ์กฐ์ฒด์™€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๊ณ , ์ด๋Š” socket๊ณผ ์—ฐ๊ฒฐ๋จ
      • tcp_input() → in_pcblookup_hash() // ๋ชฉ์ ์ง€ ์†Œ์ผ“ ์ฐพ๊ธฐ → tp = intotcpcb(inpcb) // TCP ์ƒํƒœ ๊ตฌ์กฐ ์–ป๊ธฐ
  4. TCP ์กฐ๋ฆฝ (seq → ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ)
    • ์„ธ๊ทธ๋จผํŠธ๊ฐ€ ์ •์ƒ์ ์ด๊ณ  ์ˆœ์„œ์— ๋งž์œผ๋ฉด TCP ์ˆ˜์‹  ์œˆ๋„์šฐ์— ๋”ฐ๋ผ ์ˆ˜์šฉ
      • tcp_reass()๋กœ ์กฐ๋ฆฝ ๋˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ๋„์ฐฉํ–ˆ์œผ๋ฉด ์ฆ‰์‹œ ๋ฐ˜์˜
      • sbappend()์„ ํ˜ธ์ถœํ•ด ์†Œ์ผ“ ์ˆ˜์‹  ๋ฒ„ํผ์— ๋ถ™์ž„ (mbuf ์ฒด์ธ)
        tcp_input() → tcp_reass() → sbappend(so, mbuf)
    • mbuf๋Š” ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ด๊ธด ์ปค๋„์˜ ๋ฒ„ํผ(+๋ฉ”ํƒ€๋ฐ์ดํ„ฐ) ๊ฐ์ฒด
      • so->so_rcv.sb_mb ํ•„๋“œ์— mbuf ์ฒด์ธ์ด ์ถ”๊ฐ€๋จ
      • ๋ฒ„ํผ์˜ ํฌ๊ธฐ๋Š” SO_RCVBUF ํฌ๊ธฐ ์ œํ•œ์„ ์ดˆ๊ณผํ•˜์ง€ ์•Š๋„๋ก ์กฐ์ ˆ๋จ
    • ์™œ mbu๋ฅผ ์‚ฌ์šฉํ•˜์ง€?
      • ๋„คํŠธ์›Œํฌ ๋ฐ์ดํ„ฐ๋Š” ๊ณ ์ •ํฌ๊ธฐ์˜ ๋ธ”๋ก์œผ๋กœ ์˜ค๊ฐ„๋‹ค.
      • mbuf๋Š” ๋‹ค์Œ mbuf๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ์Œ
      • ์ปค๋„์ด ์ž‘์€ ๋‹จ์œ„(mbuf)๋ฅผ ์ฒด์ธ์ฒ˜๋Ÿผ ์—ฐ๊ฒฐํ•ด์„œ TCP/IP ํŒจํ‚ท ์กฐ๋ฆฝ/์ „๋‹ฌ์— ์”€.
  5. ์œ ์ € ๊ณต๊ฐ„ ํ†ต์ง€ (wake up)
    • ์†Œ์ผ“์ด blocking read ์ค‘์ด์—ˆ๋‹ค๋ฉด → sorwakeup() ํ˜ธ์ถœ๋˜์–ด ํ”„๋กœ์„ธ์Šค ๊นจ์›€
      sorwakeup(so);
    • select/poll/epoll/kqueue ๋“ฑ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ๋Œ€๊ธฐ ์ค‘์ด์—ˆ๋‹ค๋ฉด → ํ•ด๋‹น ์ด๋ฒคํŠธ ๋ฐœ์ƒ
    • ์œ ์ € ๊ณต๊ฐ„์—์„œ recv(), read() ๋“ฑ ํ˜ธ์ถœ ์‹œ soreceive() ์ง„์ž…
  6. ์œ ์ € ๊ณต๊ฐ„ ์ˆ˜์‹  ( read()/recv() )
    • soreceive() ํ˜ธ์ถœ
    • ๋‚ด๋ถ€์ ์œผ๋กœ mbuf์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊บผ๋‚ด ์œ ์ € ๋ฒ„ํผ๋กœ ๋ณต์‚ฌ
    • ๋ฐ์ดํ„ฐ๋ฅผ ์†Œ๋น„ํ•˜๋ฉด mbuf ํ•ด์ œ (m_free())