π 곡λΆνλ μ§μ§μνμΉ΄λ μ²μμ΄μ§?
[리λ μ€ λ€νΈμν¬ νλ‘κ·Έλλ°] λ³ν μ²λ¦¬ μλ² λ³Έλ¬Έ
[리λ μ€ λ€νΈμν¬ νλ‘κ·Έλλ°] λ³ν μ²λ¦¬ μλ²
μ§μ§μνμΉ΄ 2024. 1. 31. 13:01<μμμ§ λμ μ¬λ¬ΌμΈν°λ·μ μν 리λ μ€ νλ‘κ·Έλλ° with λΌμ¦λ² 리νμ΄ μμ μ μ°Έκ³ ν΄μ μμ±νμμ΅λλ€ :-)>
β λ³ν μ²λ¦¬ μλ²
μμ μλ² μ½λλ₯Ό λΉλν ν 2λμ ν΄λΌμ΄μΈνΈκ° μ μν κ²½μ°λΌλ©΄
첫 λ²μ§Έ ν΄λΌμ΄μΈνΈλ μλ²μ λ¬Έμ μμ΄ μ μλμ§λ§,
λ λ²μ§Έ ν΄λΌμ΄μΈνΈκ° μ μνλ©΄, λ λ²μ§Έ ν΄λΌμ΄μΈνΈλ 첫 λ²μ§Έ ν΄λΌμ΄μΈνΈμ μ°κ²°μ΄ λμ΄μ§ λκΉμ§ λκΈ° μνλ‘ μκ» λλ€
μ¬λ¬ ν΄λΌμ΄μΈνΈλ₯Ό λμμ λ³λ ¬λ‘ μ²λ¦¬νκΈ° μν΄μλ λ©ν° νλ‘μΈμ€λ λ©ν° μ€λ λ κΈ°λ°μ μλ²κ° νμνλ€
λ©ν° νλ‘μΈμ€ μλ²μ κ²½μ° ν΄λΌμ΄μΈνΈμ μ μμ΄ λ€μ΄μ¬ λλ§λ€ μλ‘μ΄ νλ‘μΈμ€λ₯Ό λ§λ€μ΄μ μ²λ¦¬ν μ μλ€
BUT π¨ νλ‘μΈμ€λ₯Ό λ§λλλ° μκ°μ΄ λ§μ΄ κ±Έλ¦¬κ³ , νλ‘μΈμ€ κ° ν΅μ (IPC) μ΄ λ©ν° μ€λ λμ λΉν΄ 볡μ‘νκΈ° λλ¬Έμ μμ¦μ λ©ν° μ€λ λλ₯Ό λ λ§μ΄ μ΄λ€
λ©ν° μ€λ λ μλ²λ ν΄λΌμ΄μΈνΈμ μμ²μ΄ λ€μ΄μ¬ λλ§λ€ μλ‘μ΄ μ€λ λλ₯Ό λ§λ€μ΄μ μ²λ¦¬νλ€
λ©ν° νλ‘μΈμ€λ³΄λ€ μ½κ² μ€λ λλ₯Ό λ§λ€ μ μκ³ , μλ‘ ν΅μ μ΄ κ°λ¨νκΈ° λλ¬Έμ λ§μ΄ μ¬μ©λλ€
λ€μ€ ν΄λΌμ΄μΈνΈμ ν΅μ μ μ²λ¦¬νλ λ°©λ²μΌλ‘ λ©ν° νλ‘μΈμ€μ λ©ν° μ€λ λ λ°©μ μ΄μΈμλ I/O λ©ν° νλμ± (Multiplexing) λ°©μμ΄ μλ€
λ©ν° νλμ± λ°©μμ ν΄λΌμ΄μΈνΈμ μꡬμ¬νμ΄ λ§μ§ μμ κ²½μ° μ£Όλ‘ μ΄μ©λλλ°, μ΄λ νλμ μμΌ λμ€ν¬λ¦½νΈλ₯΄ ν¨μ¨μ μΌλ‘ μ¬μ©ν μ μκ² ν΄μ€λ€
I/O λ©ν° νλμ±μ νλμ νλ‘μΈμ€ λλ μ€λ λμμ μ¬μ©νλ λ€μ€ μ²λ¦¬ λ°©λ²μΌλ‘ ꡬλΆλλ€
κ΅¬λΆ | λ΄μ© | λΉκ³ |
ν΄λ§ (Polling) | 루νλ₯Ό μ΄μ©ν΄μ μ²λ¦¬ν΄μΌ ν μΌμ΄ μλμ§ μ£ΌκΈ°μ μΌλ‘ μ§μΌλ³΄λ€κ° μ²λ¦¬ν΄μΌ ν μμ λ€μ΄ μκΈ°λ©΄ μμ°¨μ μΌλ‘ λμκ°λ©΄μ μ²λ¦¬νλ λ°©λ² | poll |
μ λ νΈ (Selecting) | μ§μ λ νμΌ λμ€ν¬λ¦½ν°μ λ³νλ₯Ό νμΈν΄μ λ³ν (μ λ ₯, μΆλ ₯, μλ¬)κ° κ°μ§λλ©΄ ν΄λΉ μμ μ μ²λ¦¬νλ λ°©λ² | select |
μΈν°λ½νΈ (Interrupt) | νλ‘μΈμ€κ° μ΄λ€ μμ μ μ²λ¦¬νλ λμ€μ νΉμ ν μ΄λ²€νΈκ° λ°μνλ©΄ μκ·Έλ λ±μ μ΄μ©ν΄μ ν΄λΉ μ΄λ²€νΈλ₯Ό μ²λ¦¬νλ λ°©λ² | μκ·Έλ, epoll |
ν΄λ§ (polling) λ°©μμ 컀λμ΄ μ£Όλ³ μ₯μΉμκ² μΌμ μν¨ ν 루νλ₯Ό λλ©΄μ κ·Έ μΌμ΄ μλ£λμλμ§ μ£ΌκΈ°μ μΌλ‘ κ²μ¬
μΈν°λ½νΈ (interrupt) λ°©μμ μ ν리μΌμ΄μ μ΄ μ£Όλ³ μ₯μΉμκ² μΌμ μν¨ ν νλ‘μΈμ€λ λ€λ₯Έ μΌμ νλ©° λλ°μ΄μ€κ° μΌμ μλ£ν ν μκ·Έλμ΄λ λ€λ₯Έ μΈν°λ½νΈλ‘ μ리λ λ°©μ
select μ poll μ νμΌ λμ€ν¬λ¦½ν°λ₯Ό κΈ°λ°μΌλ‘ μ²λ¦¬νλ€
select μ μ΅λ 1024 κ°μ νμΌ λμ€ν¬λ¦½ν°λ§ μ²λ¦¬ν μ μμ§λ§, poll μ λ λ§μ νμΌ λμ€ν¬λ¦½ν°λ₯Ό μ²λ¦¬ν μ μλ€
selectμ pollμ΄ λͺ¨λ μ΄λ²€νΈλ₯Ό κ°μ§νκΈ° μν΄ νμΌ λμ€ν¬λ¦½ν°λ₯Ό μμ°¨μ μΌλ‘ κ²μνκ³ , μ΄λ²€νΈκ° λ°μνλ©΄ νμΌ λμ€ν¬λ¦½ν°μ μ§ν©(fd_set)μ λͺ¨λ λ³κ²½ν΄μΌ νκΈ° λλ¬Έμ μλκ° λ리λ€
μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ λ§λ€μ΄μ§ κ²μ΄ epoll
epoll μ νμΌ λμ€ν¬λ¦½ν° μμ μ νμ λ°μ§ μμΌλ©°, 리λ μ€ μ»€λμμ νμΌ λμ€ν¬λ¦½ν°λ₯Ό κ΄λ¦¬νλ―λ‘ fd_set 볡μ¬κ° νμ μμΌλ―λ‘ κ°μ₯ λΉ λ₯Έ μλλ₯Ό μ 곡νλ€
β μΈν°λ½νΈμ νΈλ©
μμ€ν μμ λ°μνλ λΉλκΈ°μ μΈ μ¬κ±΄μ μ리λ λ©μ»€λμ¦
μΈν°λ½νΈ : νμ¬ μν μ€μΈ νλ‘μΈμ€μ κ΄κ³μμ΄ νλμ¨μ΄μ μΈ μ¬κ±΄μ μ리λ λ©μ»€λμ¦
νΈλ© : νμ¬ μν μ€μΈ νλ‘κ·Έλ¨μ΄ μ λ°ν μννΈμ¨μ΄μ μΈ μ¬κ±΄μ λ°μμ μ리λ λ©μ»€λμ¦
βοΈ select ν¨μ
I/O λ©ν° νλμ±μ μν λνμ μΈ ν¨μκ° select
select() ν¨μλ νμΌ λμ€ν¬λ¦½ν° λ³νλ₯Ό νμΈνλλ°, νμΌ λμ€ν¬λ¦½ν°λ₯Ό ν΅ν΄ λ°μ΄ν° μ‘μμ μ΄ κ°λ₯ν μνμΈμ§ νμΈνλ κ²
λ³νλ₯Ό κ°μ§ν΄μ νλμ μ μ±λ‘λ₯Ό λμμ μ¬λ¬ μ¬μ©μκ° μ¬μ©ν μ μλλ‘ ν¨μ¨μ±μ κ·Ήλνν μ μλ€
select() ν¨μλ₯Ό μ¬μ©νκΈ° μν΄μλ νμΌ λμ€ν¬λ¦½ν°μ λ²μλ₯Ό μ€μ ν΄μΌ νλ€
ν¨μ¨μ μΈ μνμ μν΄ νμΈν΄μΌ νλ νμΌ λμ€ν¬λ¦½ν°μ λ²μλ₯Ό μ ννλ κ²μ΄λ€
νμμμ μκ°μ μ€μ ν μ μλλ° select() ν¨μκ° νΈμΆν λ μ΄λ²€νΈ λ°μμ λν΄ μΌλ§λ§νΌ κΈ°λ€λ¦΄ κ²μΈμ§λ₯Ό μ§μ ν μ μλ€
int select (int nfds, fd_set *readfds, fd_set *writefds, fd_Set *exceptfds, struct timeval *timeout);
select() ν¨μμ 첫 λ²μ§Έ μΈμ (nfds) λ μνλ₯Ό μ§μΌλ³Ό νμΌ λμ€ν¬λ¦½ν°μ μ μΌ λμ λ²νΈ
μΌλ°μ μΌλ‘ νμΌ λμ€ν¬λ¦½ν°μ "κ°μ₯ ν° λμ€ν¬λ¦½ν° λ²νΈ + 1" μ μ΄μ©
μ€ν μ€μ νμΌμ΄λ μμΌμ μ΄μλ€κ° λ«μΌλ©΄ νμΌ λμ€ν¬λ¦½ν°λ μ€κ° λ²νΈκ° λΉκ² λλλ°, μ΄λ nfds μ λ€μ΄κ° μ«μλ μ 체 κ°μκ° μλ μ΄λ¦° νμΌ λμ€ν¬λ¦½ν°μ μ μΌ λμ λ²νΈμ΄λ―λ‘ μ£Όμν΄λΌ
λ§μ§λ§ μΈμ (timeout) μ ν¨μ νΈμΆ ν, 무ν λκΈ° μνμ λΉ μ§μ§ μλλ‘ νμμμμ μ€μ ν μ μλ€
timeval ꡬ쑰체λ₯Ό μ¬μ©νλ©΄ λλ€
μΈμ | λ΄μ© | λΉκ³ |
readfds | μμ ν λ°μ΄ν°κ° μλμ§ νμΈ | μ λ ₯ λ²νΌμ λ°μ΄ν° μ‘΄μ¬ |
writefds | λ°μ΄ν° μ μ‘μ΄ κ°λ₯ν μνμΈμ§ νμΈ | μΆλ ₯ λ²νΌμ μΆ©λΆν μ¬μ κ³΅κ° μ‘΄μ¬ |
exceptfds | μμΌμ΄ μμΈ μν©μ΄ λ°μνλμ§ νμΈ | OOB λ©μμ§ μ μ‘ λ±μ μ¬ν |
ν¨μ νΈμΆμ μ±κ³΅νλ©΄ 0 μ΄μμ κ° λ°ν, 0μ΄ λ°νλλ©΄ timeout μΌλ‘ μ€μ λ μκ°μ νμμμμ΄ λμλ€λ μλ―Έ
μ€λ₯κ° λ°μνλ©΄ -1
select() ν¨μλ fd_set μλ£ν μ¬μ©νλ€
λ³΄κ³ μΆμ νμΌ λμ€ν¬λ¦½ν°μλ²νΈλ₯Ό fd_set μλ£νμ λ§ν¬νλλ°, κΈ°λ³Έμ μΌλ‘ μκ·Έλ λ§μ€ν¬μ²λΌ νλμ λΉνΈκ° ν΄λΉ νμΌ λμ€ν¬λ¦½ν° λ²νΈμ μΌμΉνλ ννλ‘ λμ΄ μλ€
fd_set μλ£νμ μ€μ ν ν select() ν¨μμ λ±λ‘ν΄μ μ€ννλ©΄, μ΄λ²€νΈκ° λ°μν λκΉμ§ select() ν¨μκ° λκΈ°νκ³ μλ€κ°, ν΄λΉ μ΄λ²€νΈκ° λ°μνμ λ λ³νκ° μκΈ΄ νμΌ λμ€ν¬λ¦½ν°λ₯Ό νμΈν μ μλ€
POSIX μμ μ¬μ©νλ timespec ꡬ쑰체λ₯Ό μ¬μ©νλ pselect() ν¨μλ μλ€
νμμμ μκ°μ λλ Έμ΄λ‘ μ€μ ν μ μκ³ , νμΌ λμ€ν¬λ¦½ν° μ‘°μ¬ μ€ μκ·Έλμ΄ λ°μνλ κ²μ λΈλ‘ν μ μλλ‘ μ§μνλ€
// select_server.c
// TCP μλ²μμ select() ν¨μλ₯Ό μ΄μ©νμ¬ λ³λ ¬ μ²λ¦¬νκΈ°
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERVER_PORT 5100 /* μλ²μ ν¬νΈ λ²νΈ */
int main(int argc, char **argv)
{
int ssock;
socklen_t clen;
int n;
struct sockaddr_in servaddr, cliaddr;
char mesg[BUFSIZ];
fd_set readfd; /* select( ) ν¨μλ₯Ό μν μλ£ν */
int maxfd, client_index, start_index;
int client_fd[5] = {0}; /* ν΄λΌμ΄μΈνΈμ μμΌ FD λ°°μ΄ */
/* μλ² μμΌ λμ€ν¬λ¦½ν° μ°λ€. */
if((ssock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket()");
return -1;
}
memset(&servaddr, 0, sizeof(servaddr)); /* μ΄μ체μ μ μλΉμ€ λ±λ‘ */
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERVER_PORT);
if(bind(ssock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
perror("bind()");
return -1;
}
if(listen(ssock, 8) < 0) { /* ν΄λΌμ΄μΈνΈμ μμΌλ€μ μν ν μμ± */
perror("listen()");
return -1;
}
FD_ZERO(&readfd); /* fd_set μλ£νμ λͺ¨λ 0μΌλ‘ μ΄κΈ°ν */
maxfd = ssock; /* νμ¬ μ΅λ νμΌ λμ€ν¬λ¦½ν°μ λ²νΈλ μλ² μμΌμ λμ€ν¬λ¦½ν° */
client_index = 0;
do {
FD_SET(ssock, &readfd); /* μ½κΈ° λμ κ°μ§λ₯Ό μν fd_set μλ£ν μ€μ */
/* ν΄λΌμ΄μΈνΈμ μμ μ£ΌμλΆν° λ§μ§λ§ μ£ΌμκΉμ§ fd_set μλ£νμ μ€μ */
for(start_index = 0; start_index < client_index; start_index++) {
FD_SET(client_fd[start_index], &readfd);
if(client_fd[start_index] > maxfd)
maxfd = client_fd[start_index]; /* κ°μ₯ ν° μμΌμ λ²νΈλ₯Ό μ μ₯ */
}
maxfd = maxfd + 1;
/* select( ) ν¨μμμ μ½κΈ°κ° κ°λ₯ν λΆλΆλ§ μ‘°μ¬ */
select(maxfd, &readfd, NULL, NULL, NULL); /* μ½κΈ°κ° κ°λ₯ν΄μ§ λκΉμ§ λΈλ‘νΉ */
if(FD_ISSET(ssock, &readfd)) { /* μ½κΈ°κ° κ°λ₯ν μμΌμ΄ μλ² μμΌμΈ κ²½μ° */
clen = sizeof(struct sockaddr_in); /* ν΄λΌμ΄μΈνΈμ μμ² λ°μλ€μ΄κΈ° */
int csock = accept(ssock, (struct sockaddr*)&cliaddr, &clen);
if(csock < 0) {
perror("accept()");
return -1;
} else {
/* λ€νΈμν¬ μ£Όμλ₯Ό λ¬Έμμ΄λ‘ λ³κ²½ */
inet_ntop(AF_INET, &cliaddr.sin_addr, mesg, BUFSIZ);
printf("Client is connected : %s\n", mesg);
/* μλ‘ μ μν ν΄λΌμ΄μΈνΈμ μμΌ λ²νΈλ₯Ό fd_setμ μΆκ° */
FD_SET(csock, &readfd);
client_fd[client_index] = csock;
client_index++;
continue;
}
if (client_index == 5) break;
}
/* μ½κΈ° κ°λ₯νλ μμΌμ΄ ν΄λΌμ΄μΈνΈμλ κ²½μ° */
for(start_index = 0; start_index < client_index; start_index++) {
/* for 루νλ₯Ό μ΄μ©ν΄μ ν΄λΌμ΄μΈνΈλ€μ λͺ¨λ μ‘°μ¬ */
if(FD_ISSET(client_fd[start_index], &readfd)) {
memset(mesg, 0, sizeof(mesg));
/* ν΄λΉ ν΄λΌμ΄μΈνΈμμ λ©μμ§λ₯Ό μ½κ³ λ€μ μ μ‘(Echo) */
if((n = read(client_fd[start_index], mesg, sizeof(mesg))) > 0) {
printf("Received data : %s", mesg);
write(client_fd[start_index], mesg, n);
close(client_fd[start_index]); /* ν΄λΌμ΄μΈνΈ μμΌμ λ«λλ€. */
/* ν΄λΌμ΄μΈνΈ μμΌμ μ§μ΄λ€. */
FD_CLR(client_fd[start_index], &readfd);
client_index--;
}
}
}
} while(strncmp(mesg, "q", 1));
close(ssock); /* μλ² μμΌμ λ«λλ€. */
return 0;
}
/*
ν΄λΌμ΄μΈνΈμμ ν΅μ μ μν μμΌμ μμ± ν, μ΄μ체μ μ μλΉμ€λ₯Ό λ±λ‘νκ³ , ν΄λΌμ΄μΈνΈμ μ μμ μ²λ¦¬ν μ μλ λκΈ° νλ₯Ό μμ±νλ κΈ°λ³Έ μμ
μ μνν¨
TCP μλ²μ λ€λ₯Έ λΆλΆμ select() ν¨μμμ μ¬μ©ν fd_set λ³μνμ μ μΈν λΆλΆμ
select() ν¨μλ₯Ό μ¬μ©νλλΌλ μΌλ°μ μΈ ν΄λΌμ΄μΈνΈ ν΅μ μ²λ¦¬λ κΈ°λ³Έ TCP μλ²μ λΉμ·ν¨
select() ν¨μλ₯Ό μ΄μ©ν΄μ μλ² μμΌμ΄λ ν΄λΌμ΄μΈνΈ μμΌμμ μ½μ λ°μ΄ν°κ° μλμ§ νμΈνκ³ μ΄λ₯Ό κ°κ° μ²λ¦¬νλ κ²
fd_set μλ£νμ FD_ZERO() λ§€ν¬λ‘λ₯Ό ν΅ν΄ λͺ¨λ λΉνΈλ₯Ό 0μΌλ‘ μ΄κΈ°ννκ³ , μλ² μ€μΌμ νμΌ λμ€ν¬λ¦½ν°μ λν λ²νΈλ₯Ό FD_SET() λ§€ν¬λ‘λ₯Ό ν΅ν΄ μ€μ νλ€
select() ν¨μλ₯Ό μ΄μ©νμ¬ νμ¬μ fd_set μλ£νμ λν΄ μ½κΈ°κ° κ°λ₯ν μ΄λ²€νΈκ° μλμ§ νμΈνλλ°, κ°μ₯ λ§μ§λ§ μΈμ(timeout) κ° NULL λ‘ μ€μ λμ΄ μμΌλ―λ‘ μ½κΈ°κ° κ°λ₯ν λκΉμ§ 무ν λκΈ°
μλ²μ γ
‘γΉλΌμ΄μΈνΈλ‘λΆν°μ μμ΄ λ€μ΄μ€λ©΄ select() ν¨μμμ λΉ μ Έλμ fd_set μ μ΄λ€ λΉνΈκ° μ€μ λμ΄ μλμ§ νμΈ κ°λ₯
FD_ISSET() λ§€ν¬λ‘λ₯Ό μ¬μ©νκ³ , λ§μ½ μλ² μμΌμμ μ΄λ²€νΈκ° λ°μνμΌλ©΄ accept() ν¨μλ₯Ό ν΅ν΄ ν΄λΌμ΄μΈνΈμ μ μμ λ°μλ€μ΄κ³ , fd_setμ FD_SET() λ§€ν¬λ‘λ₯Ό ν΅ν΄ μλ‘ μ μν ν΄λΌμ΄μΈνΈμ μμΌμ λν νμΌ λμ€ν¬λ¦½ν°λ₯Ό μΆκ°νλ€
μλ²λ λ€μ select() ν¨μλ‘ λμκ°μ μλ²λ ν΄λΌμ΄μΈνΈμμ λ°μ΄ν°κ° μ€λμ§ νμΈνκ³ , μλ‘μ΄ ν΄λΌμ΄μΈνΈμ μμ²μ΄ λ€μ΄μ€λ©΄ μ΄μ μμ
μ λ€μ μννλ€
μ΄λ―Έ μ μν ν΄λΌμ΄μΈνΈμμ λ©μμ§κ° λ€μ΄μ€λ κ²½μ°λΌλ©΄ λ€μ μμ
μ μννλ€
for 루νμ FD_ISSET() λ§€ν¬λ‘λ₯Ό μ΄μ©ν΄μ μ΄μ μ μ μλ ν΄λΌμ΄μΈνΈλ€μ μμΌμ λ°°μ΄μμ μ΄λ€ ν΄λΌμ΄μΈνΈλ‘λΆν° λ°μ΄ν°κ° λ€μ΄μλμ§ νμΈνκ³ , λ°μ΄ν°κ° λ€μ΄μμΌλ©΄
read() ν¨μλ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό μ½μ ν λ€μ write() ν¨μλ₯Ό ν΅ν΄ ν΄λΌμ΄μΈνΈλ‘ λμΌν γ
λ€μμ§λ₯Ό 보λΈλ€
TCP ν΄λΌμ΄μΈνΈλ₯Ό μ΄μ©ν΄μ μλ²μ μ μν μ μλ€
*/
gcc -o select_server select_server.c
./select_server &
gcc -o tcp_client tcp_client.c
./tcp_client 127.0.0.1

βοΈ epoll API
epoll μ 리λ μ€ νκ²½μμ μ¬μ©ν μ μλλ‘ λ§λ I/O ν΅μ§ κΈ°λ²μΌλ‘ μ λ ₯κ³Ό μΆλ ₯μ λ΄λΉν ν¬νΈλ₯Ό μ§μ νμ¬ μ²λ¦¬νκΈ° λλ¬Έμ select μ κ°μ΄ μ 체 νμΌ λμ€ν¬λ¦½ν°μ λν΄ μμ°¨μ μΌλ‘ κ°μνμ§ μκ³ , μ 체 νμΌ λμ€ν¬λ¦½ν°λ 볡μ¬νμ§ μλλ€
μ΄μ체μ κ° μ§μ νμΌ λμ€ν¬λ¦½ν°μ μ 보λ₯Ό λ΄μ μ μ₯μλ₯Ό κ΄λ¦¬νκ³ κ΄μ°° λμμ μν μ μ₯μμ μμ±μ μμ²νλ©΄, κ·Έ μ μ₯μμ ν΄λΉνλ νμΌ λμ€ν¬λ¦½ν° (epoll_fd) λ₯Ό λ°ννλ€
무μΈκ° μ΄λ²€νΈκ° λ°μνλ©΄ epoll_fd λ₯Ό ν΅ν΄ νμΈν μ μλ€
epollμ μ£Όλ‘ epoll_create(), epoll_ctl(), epoll_wait() ν¨μλ₯Ό μ¬μ©ν΄μ λ³ν μλ²λ₯Ό λ§λ€ μ μλ€
// epoll_server.c
// TCP μλ² μ½λλ₯Ό epoll μ ν¨μλ₯Ό μ΄μ©νμ¬ λ³λ ¬ μ²λ¦¬ν μ μλλ‘ λ³κ²½νκΈ°
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#define SERVER_PORT 5100 /* μλ²μ ν¬νΈ λ²νΈ */
#define MAX_EVENT 32
/* νμΌ λμ€ν¬λ¦½ν°λ₯Ό λλΈλ‘νΉ λͺ¨λλ‘ μ€μ */
void setnonblocking(int fd)
{
int opts = fcntl(fd, F_GETFL);
opts |= O_NONBLOCK;
fcntl(fd, F_SETFL, opts);
}
int main(int argc, char **argv)
{
int ssock, csock;
socklen_t clen;
int n, epfd, nfds = 1; /* κΈ°λ³Έ μλ² μΆκ° */
struct sockaddr_in servaddr, cliaddr;
struct epoll_event ev;
struct epoll_event events[MAX_EVENT];
char mesg[BUFSIZ];
/* μλ² μμΌ λμ€ν¬λ¦½ν°λ₯Ό μ°λ€. */
if((ssock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket()");
return -1;
}
setnonblocking(ssock); /* μλ²λ₯Ό λλΈλ‘νΉ λͺ¨λλ‘ μ€μ */
memset(&servaddr, 0, sizeof(servaddr)); /* μ΄μ체μ μ μλΉμ€ λ±λ‘ */
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERVER_PORT);
if(bind(ssock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
perror("bind()");
return -1;
}
if(listen(ssock, 8) < 0) { /* ν΄λΌμ΄μΈνΈμ μμΌλ€μ μν ν μμ± */
perror("listen()");
return -1;
}
/* epoll_create() ν¨μλ₯Ό μ΄μ©ν΄μ 컀λμ λ±λ‘ */
epfd = epoll_create(MAX_EVENT);
if(epfd == -1) {
perror("epoll_create()");
return 1;
}
/* epoll_ctl() ν¨μλ₯Ό ν΅ν΄ κ°μνκ³ μΆμ μλ² μμΌμ λ±λ‘ */
ev.events = EPOLLIN;
ev.data.fd = ssock;
if(epoll_ctl(epfd, EPOLL_CTL_ADD, ssock, &ev) == -1) {
perror("epoll_ctl()");
return 1;
}
do {
epoll_wait(epfd, events, MAX_EVENT, 500);
for(int i = 0; i < nfds; i++) {
if(events[i].data.fd == ssock) { /* μ½κΈ°κ° κ°λ₯ν μμΌμ΄ μλ² μμΌμΈ κ²½μ° */
clen = sizeof(struct sockaddr_in);
/* ν΄λΌμ΄μΈνΈμ μμ² λ°μλ€μ΄κΈ° */
csock = accept(ssock, (struct sockaddr*)&cliaddr, &clen);
if(csock > 0) {
/* λ€νΈμν¬ μ£Όμλ₯Ό λ¬Έμμ΄λ‘ λ³κ²½ */
inet_ntop(AF_INET, &cliaddr.sin_addr, mesg, BUFSIZ);
printf("Client is connected : %s\n", mesg);
setnonblocking(csock); /* ν΄λΌμ΄μΈνΈλ₯Ό λλΈλ‘νΉ λͺ¨λλ‘ μ€μ */
/* μλ‘ μ μν ν΄λΌμ΄μΈνΈμ μμΌ λ²νΈλ₯Ό fd_setμ μΆκ° */
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = csock;
epoll_ctl(epfd, EPOLL_CTL_ADD, csock, &ev);
nfds++;
continue;
}
} else if(events[i].events & EPOLLIN) { /* ν΄λΌμ΄μΈνΈμ μ
λ ₯ */
if(events[i].data.fd < 0) continue; /* μμΌμ΄ μλ κ²½μ°μ μ²λ¦¬ */
memset(mesg, 0, sizeof(mesg));
/* ν΄λΉ ν΄λΌμ΄μΈνΈμμ λ©μμ§λ₯Ό μ½κ³ λ€μ μ μ‘(Echo) */
if((n = read(events[i].data.fd, mesg, sizeof(mesg))) > 0) {
printf("Received data : %s", mesg);
write(events[i].data.fd, mesg, n);
close(events[i].data.fd); /* ν΄λΌμ΄μΈνΈ μμΌμ λ«κ³ μ§μ΄λ€. */
epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
nfds--;
}
}
}
} while(strncmp(mesg, "q", 1));
close(ssock); /* μλ² μμΌμ λ«λλ€. */
return 0;
}
/*
TCP μλ²μ κ°μ΄ μμΌμ μμ±ν ν bind()μ listen() ν¨μλ₯Ό μ΄μ©ν΄μ μλΉμ€λ₯Ό μ΄μ체μ μ λ±λ‘νλ€
epoll_create() ν¨μλ₯Ό μ΄μ©ν΄μ κ°μνκ³ μΆμ νμΌ λμ€ν¬λ¦½ν°μ μ«μλ₯Ό λ£μ΄μ€¬λλ°, μλ² + ν΄λΌμ΄μΈνΈμ μλ‘ μ€μ νλ©΄ λλ€
epoll_ctl() ν¨μμ μλ² μμΌμ μΆκ°νμλ€. μλ² μμΌμ ν΄λΌμ΄μΈνΈμ μ μμ κ°μν κ²μ΄λ―λ‘ μ
λ ₯ (EPOLLIN) μΌλ‘ μ΄λ²€νΈ μ€μ
μλ²μ ν΄λΌμ΄μΈνΈκ° μ μλλ©΄ epoll_wait() ν¨μμμ λμ΄κ°κ² λλλ°, μ΄λ²€νΈκ° λ°μν μμΌμ΄ μλ²μ΄λ©΄ accpet() ν¨μλ₯Ό ν΅ν΄μ λ°μλ€μ΄κ³ ,
epoll_ctl() ν¨μλ₯Ό ν΅ν΄ λ€μ 컀λμ ν΄λΌμ΄μΈνΈμ μμΌ λμ€ν¬λ¦½ν°λ₯Ό κ°μν μ μλλ‘ μΆκ°νλ€
ν΄λΌμ΄μΈνΈ μμΌμΌλ‘λΆν° μ΄λ²€νΈκ° λ°μνλ©΄ ν΄λΌμ΄μΈνΈμμ μ¨ λ°μ΄ν°λ₯Ό μ½μ΄μ λ€μ ν΄λΌμ΄μΈνΈλ‘ μ μ‘(μμ½) νκ³ ν΄λΌμ΄μΈνΈνν
μμΌμ λ«μ ν
epoll_ctl() ν¨μλ₯Ό ν΅ν΄ 컀λμ μΆκ°ν ν΄λΌμ΄μΈνΈ μμΌμ κ°μλ₯Ό μμ νλ€
ν΄λΌμ΄μΈνΈλ tcl_client λ‘ μ¬μ©
epoll μ΄ select μ λΉν΄ μλλ λΉ λ₯΄μ§λ§, νΉμ νλ«νΌμμλ μ¬μ©ν μ μλ€
gani@gani:~/raspi/NetworkProgramming $ gcc -o epoll_server epoll_server.c
gani@gani:~/raspi/NetworkProgramming $ ./epoll_server &
gani@gani:~/raspi/NetworkProgramming $ gcc -o tcp_client tcp_client.c
gani@gani:~/raspi/NetworkProgramming $ ./tcp_client
gani@gani:~/raspi/NetworkProgramming $ ./tcp_client 127.0.0.1
*/
gcc -o epoll_server epoll_server.c
./epoll_server &
gcc -o tcp_client tcp_client.c
./tcp_client
./tcp_client 127.0.0.1
