์์ผ ๋ท์กฐ์ฌ์ข ํด๋ดค์ต๋๋ค
: ๊ฐ๋ฐ์๊ฐ ๋คํธ์ํฌ ํต์ ์ ํ ์ ์๋๋ก ์ถ์ํ๋, ํ์ผ ์ ์ฌ 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() ๋ฑ ํ๋กํ ์ฝ๋ณ ๊ตฌํ์ฒด ์ฐ๊ฒฐ
- pr_usrreqs์ ์ปค๋ ๋คํธ์ํฌ ์์ผ ์ธํฐํ์ด์ค ํจ์๋ค์ด ์ง์ฝ๋จ
- 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
- ์ฌ์ฉ์ ํธ์ถ
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- AF_INET : IPv4 ๋๋ฉ์ธ ์ ํ
- SOCK_STREAM : ์คํธ๋ฆผ ํ์ (TCP)
- IPPROTO_TCP : TCP ํ๋กํ ์ฝ ๋ช ์
- ์ปค๋ ๋ด๋ถ ์ ์ฐจ (
sys_socket()
→socreate()
)- ์ปค๋์
domain[]
๋ฆฌ์คํธ์์ AF_INET ๋๋ฉ์ธ์ ์ฐพ์. - AF_INET ๋๋ฉ์ธ์
protosw[]
๋ฐฐ์ด์ ์ํํ๋ฉด์pr_type == SOCK_STREAM
&&pr_protocol == IPPROTO_TCP
์ธ ํ๋กํ ์ฝ ์ค์์น ์ํธ๋ฆฌ๋ฅผ ์ฐพ์. - ์ด ์ํธ๋ฆฌ๋ฅผ ์ ํํ์ฌ ์์ผ์
so_proto
ํ๋์ ์ฐ๊ฒฐ.socket->so_proto = protosw_entry
- ์ปค๋์
- ํ๋กํ ์ฝ ์ ์ด ๋ธ๋ก(PCB) ์์ฑ ๋ฐ ์ฐ๊ฒฐ
- ํ๋กํ ์ฝ ์ค์์น ๊ตฌ์กฐ์ฒด(
protosw
) ์์pr_usrreqs->pru_attach()
ํจ์ ํธ์ถ (TCP:tcp_attach()
). tcp_attach()
๋ด์์ ๋ค์์ด ์ํ๋จ:struct inpcb
ํ ๋น ๋ฐ ์ด๊ธฐํ
IP ์ฃผ์ ๋ฐ ํฌํธ ๋ฑ ๋คํธ์ํฌ ์๋ณ์์ฉ ์ํ ์ ์ฅ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
- ์์ผ ์์ฑ (์์ผ๊ณผ ์ ์ก๊ณ์ธต ๋ฐ์ธ๋ฉ)
- ์ ์ ๊ณต๊ฐ:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- ์ปค๋ ๋ด๋ถ:
socket()
์์คํ ์ฝ →sys_socket()
socreate()
ํธ์ถ:- ์ฃผ์ ํจ๋ฐ๋ฆฌ (e.g.,
AF_INET
) - ํ์
(e.g.,
SOCK_STREAM
) - ํ๋กํ ์ฝ (e.g.,
IPPROTO_TCP
)
- ์ฃผ์ ํจ๋ฐ๋ฆฌ (e.g.,
- ๋ด๋ถ์์ ๋๋ฉ์ธ(domain,
domain[]
)๊ณผ ํ๋กํ ์ฝ ์ค์์น(protosw[]
)๋ฅผ ํ์ struct socket
๊ฐ์ฒด ์์ฑ- ๊ด๋ จ ํ๋กํ ์ฝ ์ ์ด ๋ธ๋ก (
inpcb
,tcpcb
) ๋ฑ๋ ํจ๊ป ํ ๋น
- ์ ์ ๊ณต๊ฐ:
- ์์ผ ๋ฐ์ธ๋ฉ (์ ํ์ ) (์์ ๋ฐ์ธ๋ฉ๊ณผ๋ ๋ค๋ฆ)
- ์ ์ ๊ณต๊ฐ:
bind(sockfd, ...);
- ์ปค๋ ๋ด๋ถ:
sys_bind()
→sobind()
→ ํ๋กํ ์ฝ ๋ ๋ฒจ์pr_bind()
ํธ์ถ- ์: TCP๋ผ๋ฉด
tcp_usrreq()
์์PRU_BIND
์ฒ๋ฆฌ
- ์: TCP๋ผ๋ฉด
inpcb
์ ๋ก์ปฌ ์ฃผ์(port, IP) ์ค์
- ์ ์ ๊ณต๊ฐ:
- ์์ผ listen (์๋ฒ์ ๊ฒฝ์ฐ)
- ์ ์ ๊ณต๊ฐ:
listen(sockfd, backlog);
- ์ปค๋ ๋ด๋ถ:
sys_listen()
→solisten()
- ํ๋กํ ์ฝ์
pr_listen()
์ฒ๋ฆฌ (e.g., TCP์์ passive open) so_options
์SO_ACCEPTCONN
์ค์
- ํ๋กํ ์ฝ์
- ๋ฐฑ๋ก๊ทธ ํ ์์ฑ
- ์ ์ ๊ณต๊ฐ:
- ์์ผ ์ฐ๊ฒฐ
- ํด๋ผ์ด์ธํธ:
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๊ณผ ๋ถ๋ฆฌ๋ ์๋ก์ด ์ฐ๊ฒฐ ์์ผ ๋ฐํ
- ์ปค๋์์
- ํด๋ผ์ด์ธํธ:
- ๋ฐ์ดํฐ ์ก์์
- ์ ์ ๊ณต๊ฐ:
write(sockfd, buffer, len); // send
read(sockfd, buffer, len); // recv
- ์ปค๋:
sosend()
/soreceive()
ํธ์ถ- TCP:
tcp_output()
/tcp_input()
→ mbuf ๋จ์๋กso_snd
/so_rcv
ํ์ ๋ถ์ - ์์ ๋ TCP ์ธ๊ทธ๋จผํธ๋
mbuf
๋ก ๊ฐ์ธ์ ธ ์์ผ ์์ ๋ฒํผ๋ก ๋ค์ด์ด
- ์ ์ ๊ณต๊ฐ:
- ์์ผ ์ข
๋ฃ (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()]
- ์ ์ ๊ณต๊ฐ์์
write()
ํธ์ถ- ์์ผ์ ํจ์
sosend()
→ mbuf์ ๋ฐ์ดํฐ ์ ์ฅ
- ์์ผ์ ํจ์
sosend()
ํธ์ถ → ์์ผ ๋ฒํผ ํ์ธ ๋ฐ ๋ฐ์ดํฐ ๋ณต์ฌso == struct socket
— ์์ผ ์ ๋ฐ ์ํbuf == struct sockbuf
— ์ก์ ๋ฒํผ (so_snd
)- ๋ด๋ถ ์ฒ๋ฆฌ:
sbspace(&so->so_snd)
๋ก ์ก์ ๋ฒํผ์ ์ฌ์ ์๋์ง ํ์ธ- ์ฌ์ ์์ผ๋ฉด:
- blocking ๋ชจ๋๋ฉด:
sbwait()
๋ก sleep → wakeup ๊ธฐ๋ค๋ฆผ - non-blocking ๋ชจ๋๋ฉด:
EWOULDBLOCK
๋ฐํ
- blocking ๋ชจ๋๋ฉด:
- ์ฌ์ ์์ผ๋ฉด:
- ์ ์ ์
buf
๋ฅผmbuf
์ฒด์ธ์ผ๋ก ๋ณต์ฌ - ์ด mbuf๋ค์
so->so_snd.sb_mb
์ ์ฐ๊ฒฐ
- ์ ์ ์
- ํ๋กํ ์ฝ ์ฒ๋ฆฌ ํจ์ ํธ์ถ (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๋ ์ก์ ๋ฒํผ๋ฅผ ์ฐธ์กฐํด ์ธ๊ทธ๋จผํธ๋ฅผ ๋ง๋ค๊ณ , ๋ณด๋ด๊ธฐ ์์ํจ
- → ๋ด๋ถ์ ์ผ๋ก ์ฆ์
- sosend()
- TCP ๊ณ์ธต์์ ์ก์ ์ธ๊ทธ๋จผํธ ์์ฑ (
tcp_output()
)- ์ฌ๊ธฐ์ ๋๋์ด TCP ํค๋๊ฐ ๋ถ์ ์ธ๊ทธ๋จผํธ๊ฐ ์์ฑ๋จ.
- ์ฃผ์ ์ฒ๋ฆฌ:
tcp_output()
์ ์์ผ์so_snd.sb_mb
์์ mbuf ๋ฐ์ดํฐ ์ฝ์- ์ธ๊ทธ๋จผํธ ํฌ๊ธฐ ๊ณ์ฐ (MSS ๊ณ ๋ ค)
- ํ์ํ TCP ํค๋ ์์ฑ (SEQ ๋ฒํธ ๋ฑ)
- ๋ฒํผ๋ก๋ถํฐ ๋ฐ์ดํฐ
m_copydata()
๋ฑ์ผ๋ก ์กฐ๋ฆฝ - ํจํท์ IP ๊ณ์ธต์ ๋๊น:
ip_output()
ํธ์ถ
- IP ๊ณ์ธต → ์ธํฐํ์ด์ค ๋๋ผ์ด๋ฒ
ip_output()
์ ๋ผ์ฐํ ํ ์ด๋ธ, MTU ํ์ธ, IP ํค๋ ์์ฑ- ์ดํ
if_output()
ํตํด NIC ๋๋ผ์ด๋ฒ๋ก ํจํท ์ ๋ฌ - ๋๋ผ์ด๋ฒ๊ฐ DMA ๋ฑ์ผ๋ก NIC์ ํจํท์ ๋๊ฒจ ์ค์ ์ ์ก
- ์ก์ ์๋ฃ ํ ์ฒ๋ฆฌ
- ํจํท์ด ์ ์ก๋๋ค๊ณ ํด์ ๋ฐ๋ก ๋ฒํผ์์ ์ ๊ฑฐ๋์ง ์์
- 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() ๋ก ์ฝ์ ]
- NIC → ์ปค๋ ์ง์
(Ethernet ์์ )
- ๋คํธ์ํฌ ์นด๋(NIC)๊ฐ ์ธํฐ๋ฝํธ๋ฅผ ๋ฐ์์์ผ ํจํท์ ์ปค๋๋ก ์ ๋ฌ
- ์ปค๋์ ๋๋ผ์ด๋ฒ ๋ ๋ฒจ์์ ์ด๋๋ท ํ๋ ์ ์์ ์ฒ๋ฆฌ
- ์ด๋๋ท ํ๋ ์์์ EtherType(0x0800) → IPv4๋ก ์๋ณ๋จ
`ether_input() → ip_input()``
- 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
- 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 ์ํ ๊ตฌ์กฐ ์ป๊ธฐ
- IP ์ฃผ์ + ํฌํธ ๋ฒํธ 4์์ผ๋ก ๋งค์นญ๋๋
- IP ํ์ด๋ก๋๋ฅผ TCP ์ธ๊ทธ๋จผํธ๋ก ํด์
- 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 ํจํท ์กฐ๋ฆฝ/์ ๋ฌ์ ์.
- ์ธ๊ทธ๋จผํธ๊ฐ ์ ์์ ์ด๊ณ ์์์ ๋ง์ผ๋ฉด TCP ์์ ์๋์ฐ์ ๋ฐ๋ผ ์์ฉ
- ์ ์ ๊ณต๊ฐ ํต์ง (wake up)
- ์์ผ์ด blocking read ์ค์ด์๋ค๋ฉด →
sorwakeup()
ํธ์ถ๋์ด ํ๋ก์ธ์ค ๊นจ์sorwakeup(so);
- select/poll/epoll/kqueue ๋ฑ ์ด๋ฒคํธ ๊ธฐ๋ฐ ๋๊ธฐ ์ค์ด์๋ค๋ฉด → ํด๋น ์ด๋ฒคํธ ๋ฐ์
- ์ ์ ๊ณต๊ฐ์์
recv()
,read()
๋ฑ ํธ์ถ ์soreceive()
์ง์
- ์์ผ์ด blocking read ์ค์ด์๋ค๋ฉด →
- ์ ์ ๊ณต๊ฐ ์์ ( read()/recv() )
soreceive()
ํธ์ถ- ๋ด๋ถ์ ์ผ๋ก mbuf์์ ๋ฐ์ดํฐ๋ฅผ ๊บผ๋ด ์ ์ ๋ฒํผ๋ก ๋ณต์ฌ
- ๋ฐ์ดํฐ๋ฅผ ์๋นํ๋ฉด mbuf ํด์ (
m_free()
)