μ¬μ©ν ν¨μμ λν μ§λ¬Έ ( feat. chatGPT )
π gai_strerror κ° λμ§?
π°
gai_strerror() ν¨μλ λ€νΈμν¬ ν¨μ μ€μ getaddrinfo()λ getnameinfo()μ ν¨κ» μ¬μ©λλ©°, μ΄ ν¨μλ€μ΄ λ°ννλ μ€λ₯ μ½λλ₯Ό λ¬Έμμ΄λ‘ λ³ννλ μν μ ν©λλ€.
μ¦, gai_strerror() ν¨μλ μΈμλ‘ λ°μ error μ½λμ ν΄λΉνλ μ€λ₯ λ©μμ§λ₯Ό λ°νν©λλ€. μ΄ ν¨μλ
μλ₯Ό λ€μ΄, getaddrinfo() ν¨μκ° μ€ν¨νλ©΄ ν΄λΉ ν¨μλ -1μ λ°ννκ³ , μ€λ₯ μ 보λ gai_strerror() ν¨μλ₯Ό νΈμΆνμ¬ νμΈν μ μμ΅λλ€.
π htons κ° λμΌ?
π°
htons() ν¨μλ "Host to Network Short"μ μ½μ΄λ‘, 16λΉνΈ short νμμ λ°μ΄ν°λ₯Ό νΈμ€νΈ λ°μ΄νΈ μ€λλ‘ ννλ λ°μ΄ν°μμ λ€νΈμν¬ λ°μ΄νΈ μ€λλ‘ λ³ννλ ν¨μμ λλ€.
λ€νΈμν¬ λ°μ΄νΈ μ€λλ λΉ
μλμμΌλ‘ μ μλμ΄ μκΈ° λλ¬Έμ, htons() ν¨μλ νΈμ€νΈμμ μ¬μ©νλ 리ν μλμ λ°μ΄νΈ μ€λλ₯Ό λ€νΈμν¬μμ μ¬μ©νλ λΉ
μλμ λ°μ΄νΈ μ€λλ‘ λ³νν©λλ€. μ΄ ν¨μλ
μλ₯Ό λ€μ΄, short νμμ λ³μμΈ portκ° λ¦¬ν μλμ λ°μ΄νΈ μ€λλ‘ ννλμ΄ μλ€λ©΄, htons() ν¨μλ₯Ό μ¬μ©νμ¬ λ€νΈμν¬ λ°μ΄νΈ μ€λλ‘ λ³νν μ μμ΅λλ€.
#include <arpa/inet.h>
short port = 8080;
unsigned short net_port = htons(port);
μ μ½λμμ net_portλ 16λΉνΈ short νμμ port λ³μλ₯Ό λ€νΈμν¬ λ°μ΄νΈ μ€λλ‘ λ³νν κ²°κ³Όλ₯Ό μ μ₯νκ³ μμ΅λλ€. μ΄λ κ² λ³νλ λ°μ΄ν°λ λ€νΈμν¬ μμμ μ μ‘λλ λ°μ΄ν° νμκ³Ό νΈνλκΈ° λλ¬Έμ, λ€νΈμν¬ νλ‘κ·Έλλ°μμ λ§€μ° μ€μν μν μ ν©λλ€.
λ€νΈμν¬ νλ‘κ·Έλλ°μμ htons() ν¨μλ₯Ό μ¬μ©νλ κ°λ¨ν μμ λ₯Ό 보μ¬λλ¦¬κ² μ΅λλ€. μ΄ μμ λ ν΄λΌμ΄μΈνΈ-μλ² λͺ¨λΈμ μ΄μ©νμ¬ ν΄λΌμ΄μΈνΈκ° μλ²λ‘ λ©μμ§λ₯Ό μ μ‘νλ μμ μ λλ€.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT 8080
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in server_addr;
char message[256];
// μμΌ μμ±
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// μλ² μ£Όμ μ€μ
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
server_addr.sin_port = htons(SERVER_PORT);
// μλ²μ μ°κ²°
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}
// λ©μμ§ μ μ‘
printf("Enter a message: ");
fgets(message, sizeof(message), stdin);
write(sock, message, strlen(message));
// μμΌ μ’
λ£
close(sock);
return 0;
}
μ μ½λμμ htons() ν¨μλ server_addr ꡬ쑰체μ sin_port λ©€λ²μ μ¬μ©λμμ΅λλ€. ν΄λΌμ΄μΈνΈλ SERVER_PORT μμ κ°μ 리ν μλμμΌλ‘ νννκ³ μμ§λ§, htons() ν¨μλ₯Ό μ¬μ©νμ¬ μ΄λ₯Ό λΉ μλμμΌλ‘ λ³ννμ¬ server_addr ꡬ쑰체μ sin_port λ©€λ²μ ν λΉνμμ΅λλ€. μ΄λ κ² λΉ μλμμΌλ‘ ννλ sin_port κ°μ connect() ν¨μμμ μλ²μμ μ°κ²° μ μ¬μ©λ©λλ€.
π select, poll, epoll, kqueue μ νΉμ§κ³Ό μ°¨μ΄μ μ΄ λμ¬?
π°
select, poll, epoll, kqueueμ λͺ¨λ I/O λ©ν°νλ μ± κΈ°λ²μ ꡬννλ μμ€ν μ½μ λλ€. μ΄λ¬ν μμ€ν μ½μ νλμ νλ‘μΈμ€κ° μ¬λ¬ κ°μ νμΌ λμ€ν¬λ¦½ν°λ₯Ό λͺ¨λν°λ§νκ³ , μ¬λ¬ κ°μ νμΌ λμ€ν¬λ¦½ν° μ€μμ I/O μ΄λ²€νΈκ° λ°μν κ²μ κ°μ§νμ¬ μ΄λ₯Ό μ²λ¦¬ν μ μλλ‘ λμμ€λλ€.
νμ§λ§ select, poll, epoll, kqueue κ°κ°μ νΉμ§κ³Ό μ°¨μ΄μ μ λ€μκ³Ό κ°μ΅λλ€.
βοΈ select
selectλ κ°μ₯ μ€λλ I/O λ©ν°νλ μ± κΈ°λ²μΌλ‘, νμΌ λμ€ν¬λ¦½ν°μ μν λ³νλ₯Ό κ°μνκΈ° μν΄ fd_setμ΄λΌλ λΉνΈλ§΅ μλ£κ΅¬μ‘°λ₯Ό μ¬μ©ν©λλ€. selectλ μλμ μΌλ‘ κ°λ¨νκ³ , λλΆλΆμ μ΄μ 체μ μμ μ§μλ©λλ€. κ·Έλ¬λ λΉνΈλ§΅μ ν¬κΈ°κ° μ νλμ΄ μκΈ° λλ¬Έμ, λͺ¨λν°λ§ν μ μλ νμΌ λμ€ν¬λ¦½ν°μ μμλ μ νμ΄ μμ΅λλ€. λν, selectλ λͺ¨λ νμΌ λμ€ν¬λ¦½ν°λ₯Ό μμ°¨μ μΌλ‘ νμνλ―λ‘, λμ©λμ νμΌ λμ€ν¬λ¦½ν° μ§ν©μμλ μ±λ₯ λ¬Έμ κ° λ°μν μ μμ΅λλ€.
βοΈ poll
pollμ selectμ λ§μ°¬κ°μ§λ‘ λΉνΈλ§΅μ μ¬μ©νμ¬ νμΌ λμ€ν¬λ¦½ν°μ μν λ³νλ₯Ό κ°μν©λλ€. κ·Έλ¬λ selectμ λ¬λ¦¬ νμΌ λμ€ν¬λ¦½ν° μμ μ νμ΄ μμΌλ©°, μ±λ₯λ selectλ³΄λ€ μ°μν©λλ€. νμ§λ§ μ¬μ ν νμΌ λμ€ν¬λ¦½ν°λ₯Ό μμ°¨μ μΌλ‘ νμνλ―λ‘, λμ©λμ νμΌ λμ€ν¬λ¦½ν° μ§ν©μμλ μ±λ₯ λ¬Έμ κ° λ°μν μ μμ΅λλ€.
βοΈ epoll
epollμ 리λ
μ€μμ μ¬μ©λλ I/O λ©ν°νλ μ± κΈ°λ²μΌλ‘, μ΄λ²€νΈ κΈ°λ°μΌλ‘ λμν©λλ€. epollμ selectμ pollμ μ±λ₯ λ¬Έμ λ₯Ό κ°μ νκΈ° μν΄ κ³ μλμμ΅λλ€. epollμ μ΄λ²€νΈκ° λ°μν νμΌ λμ€ν¬λ¦½ν°λ§ λ°ννκΈ° λλ¬Έμ, λμ©λμ νμΌ λμ€ν¬λ¦½ν° μ§ν©μμλ λΉ λ₯΄κ³ ν¨μ¨μ μΌλ‘ μ΄λ²€νΈλ₯Ό μ²λ¦¬ν μ μμ΅λλ€. λν, epollμ μμ², μμλ§ κ° μ΄μμ νμΌ λμ€ν¬λ¦½ν°λ₯Ό λͺ¨λν°λ§ν μ μμ΅λλ€.
βοΈ kqueue
kqueueμ FreeBSDμ macOSμμ μ¬μ©λλ I/O λ©ν°νλ μ± μ€ν λ°©μμ epollκ³Ό μ μ¬νμ§λ§, kqueueμ epollλ³΄λ€ λ λ§μ μ΄λ²€νΈ μ νμ μ§μνκ³ , μ΄λ²€νΈ λ°μ μ λ°μ΄ν°λ₯Ό λ°νν μ μμ΅λλ€. λν, kqueueμ νμΌ λμ€ν¬λ¦½ν°μ λ€λ₯Έ 리μμ€(μ: νλ‘μΈμ€, νμ΄λ¨Έ λ±)λ₯Ό λμμ κ΄λ¦¬ν μ μμΌλ―λ‘, λ€μν μ©λλ‘ νμ©λ μ μμ΅λλ€. kqueueμ epollλ³΄λ€ μλμ μΌλ‘ λ릴 μ μμ§λ§, λ§€μ° λμ μ²λ¦¬λμ κ°λ μ΄ν리μΌμ΄μ
μμλ λ λμ μ±λ₯μ λ°νν μ μμ΅λλ€.
μ΄λ¬ν select, poll, epoll, kqueueμ νΉμ§κ³Ό μ°¨μ΄μ μ κ³ λ €νμ¬, κ°λ°νλ €λ μ΄ν리μΌμ΄μ μ μꡬμ¬νκ³Ό μ΄μ 체μ νκ²½μ λ°λΌ μ μ ν I/O λ©ν°νλ μ± κΈ°λ²μ μ νν μ μμ΅λλ€.
π getaddrinfo, freeaddrinfoμ λν΄μ μ€λͺ ν΄μ£Όλ ΄
π°
getaddrinfoλ νΈμ€νΈ μ΄λ¦κ³Ό μλΉμ€ μ΄λ¦(νΉμ ν¬νΈ λ²νΈ)μ μ λ ₯ λ°μ ν΄λΉ νΈμ€νΈμ μλΉμ€μ λν μ£Όμ μ 보λ₯Ό κ°μ Έμ€λ ν¨μμ λλ€. μ΄ ν¨μλ IPv4μ IPv6λ₯Ό λͺ¨λ μ§μνλ©°, μ¬λ¬ κ°μ μ£Όμ μ 보λ₯Ό λ°νν μ μμ΅λλ€. μ΄λ¬ν λ€μν μ£Όμ μ 보λ struct addrinfo ꡬ쑰체μ ννλ‘ λ°νλ©λλ€.
getaddrinfo ν¨μλ₯Ό μ¬μ©νκΈ° μ μλ λ°λμ ν΄λΉ ꡬ쑰체λ₯Ό μ΄κΈ°νν΄μΌ ν©λλ€. λν, getaddrinfo ν¨μλ₯Ό μ¬μ©ν νμλ λ°νλ addrinfo ꡬ쑰체λ₯Ό λ©λͺ¨λ¦¬μμ ν΄μ ν΄μ£Όμ΄μΌ νλλ°, μ΄λ₯Ό μν΄ freeaddrinfo ν¨μλ₯Ό μ¬μ©ν©λλ€.
freeaddrinfo ν¨μλ getaddrinfo ν¨μκ° λ°νν addrinfo ꡬ쑰체μ λ©λͺ¨λ¦¬λ₯Ό ν΄μ νλ μν μ ν©λλ€. μ΄ ν¨μλ getaddrinfo ν¨μκ° λ°νν addrinfo ꡬ쑰체λ₯Ό μΈμλ‘ λ°μ ν΄λΉ ꡬ쑰체μ λ©λͺ¨λ¦¬λ₯Ό ν΄μ νλ©°, μ΄λ ꡬ쑰체 λ΄λΆμ μλ ai_next ν¬μΈν°λ μ¬κ·μ μΌλ‘ ν΄μ ν©λλ€. μ΄λ₯Ό ν΅ν΄ λ©λͺ¨λ¦¬ λμλ₯Ό λ°©μ§ν μ μμ΅λλ€.
μλ₯Ό λ€μ΄, μλλ getaddrinfoμ freeaddrinfoλ₯Ό μ¬μ©νμ¬ κ΅¬κΈμ DNS μλ² μ£Όμ μ 보λ₯Ό κ°μ Έμ€κ³ λ©λͺ¨λ¦¬λ₯Ό ν΄μ νλ μμ μ½λμ λλ€.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main()
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int status;
/* μ΄κΈ°ν */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* IPv4 λλ IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* UDP μμΌ */
hints.ai_flags = AI_PASSIVE; /* νΈμ€νΈ μ΄λ¦μ΄ μλ κ²½μ° */
/* ꡬκΈμ DNS μλ² μ£Όμ μ 보 κ°μ Έμ€κΈ° */
status = getaddrinfo("8.8.8.8", "53", &hints, &result);
if (status != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
exit(EXIT_FAILURE);
}
/* κ°μ Έμ¨ μ£Όμ μ 보 μΆλ ₯ */
for (rp = result; rp != NULL; rp = rp->ai_next) {
char host[NI_MAXHOST], service[NI_MAXSERV];
status = getnameinfo(rp->ai_addr, rp->ai_addrlen,
host, NI_MAXHOST,
service, NI_MAXSERV,
NI_NUMERICHOST | NI_NUMERICSERV);
if (status != 0) {
fprintf(stderr, "getnameinfo: %s\n", gai_strerror(status));
exit(EXIT_FAILURE);
}
printf("IP address: %s, Port number: %s\n", host, service);
}
/* addrinfo ꡬ쑰체μ λ©λͺ¨λ¦¬ ν΄μ */
freeaddrinfo(result);
return 0;
}
getaddrinfo ν¨μλ λ€μκ³Ό κ°μ λ€ κ°μ μΈμλ₯Ό λ°μ΅λλ€.
-
node: νΈμ€νΈ μ΄λ¦ λλ IP μ£Όμλ₯Ό μ§μ νλ λ¬Έμμ΄μ λλ€. μ΄ μΈμλ νμμ μ΄λ©°, NULLμ΄λ λΉ λ¬Έμμ΄("")μ μ λ¬ν μ μμ΅λλ€. λ§μ½ NULLμ΄λ λΉ λ¬Έμμ΄("")μ μ λ¬ν κ²½μ°μλ local IP μ£Όμκ° λ°νλ©λλ€.
-
service: μλΉμ€ μ΄λ¦ λλ ν¬νΈ λ²νΈλ₯Ό μ§μ νλ λ¬Έμμ΄μ λλ€. μ΄ μΈμλ NULLμ΄λ λΉ λ¬Έμμ΄("")μ μ λ¬ν μ μμ΅λλ€. λ§μ½ NULLμ΄λ λΉ λ¬Έμμ΄("")μ μ λ¬ν κ²½μ°μλ 0μ΄ λ°νλ©λλ€.
-
hints: struct addrinfo ꡬ쑰체μ ν¬μΈν°μ λλ€. μ΄ κ΅¬μ‘°μ²΄λ₯Ό μ¬μ©νμ¬ λ°νλ°κ³ μ νλ μ£Όμ μ 보μ νΉμ±μ μ§μ ν μ μμ΅λλ€. μ΄ κ΅¬μ‘°μ²΄λ₯Ό NULLλ‘ μ λ¬νλ κ²½μ°, getaddrinfo ν¨μλ κΈ°λ³Έκ°μ μ¬μ©ν©λλ€.
-
res: struct addrinfo ꡬ쑰체μ ν¬μΈν°μ λλ€. μ΄ ν¬μΈν°κ° κ°λ¦¬ν€λ ꡬ쑰체μλ getaddrinfo ν¨μκ° λ°νν μ£Όμ μ λ³΄κ° μ μ₯λ©λλ€. μ΄ ν¬μΈν°κ° NULLμΈ κ²½μ°, getaddrinfo ν¨μλ λ°νλ μ£Όμ μ 보λ₯Ό 무μν©λλ€.
hints ꡬ쑰체μ λ©€λ² λ³μλ‘λ ai_family, ai_socktype, ai_protocol, ai_flags λ±μ΄ μμΌλ©°, μ΄λ€μ ν΅ν΄ λ°νλ°κ³ μ νλ μ£Όμ μ 보μ νΉμ±μ μ§μ ν μ μμ΅λλ€. μμΈν λ΄μ©μ man getaddrinfoλ₯Ό μ°Έκ³ νμκΈ° λ°λλλ€.
π setsockopt, getsockname, getprotobyname ν¨μμ λν΄ μ€λͺ ν΄μ£Όλ ¨?
π° κ° ν¨μμ λν΄ κ°λ¨ν μ€λͺ μ λλ¦¬κ² μ΅λλ€.
βοΈ setsockopt
setsockopt ν¨μλ μμΌμ μ΅μ
κ°μ μ€μ ν©λλ€. μ΄ ν¨μλ₯Ό μ¬μ©νμ¬ μμΌμ μ‘μμ λ²νΌ ν¬κΈ°, λΈλ‘λμΊμ€νΈ κ°λ₯ μ¬λΆ, μμΌμ νμ
λ±μ μ€μ ν μ μμ΅λλ€. ν¨μμ νλ‘ν νμ
μ λ€μκ³Ό κ°μ΅λλ€.
#include <sys/types.h>
#include <sys/socket.h>
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
- sockfd: μμΌ νμΌ λμ€ν¬λ¦½ν°μ
λλ€.
- level: μ΅μ
μ νλ‘ν μ½ μμ€μ
λλ€. μΌλ°μ μΌλ‘ SOL_SOCKETμ μ¬μ©ν©λλ€.
- optname: μ€μ νλ €λ μ΅μ
μ μ΄λ¦μ
λλ€. μλ₯Ό λ€μ΄ μμΌμ μ‘μμ λ²νΌ ν¬κΈ°λ₯Ό μ€μ νλ €λ©΄ SO_SNDBUF λλ SO_RCVBUFλ₯Ό μ¬μ©ν©λλ€.
- optval: μ€μ νλ €λ μ΅μ
κ°μ
λλ€.
- optlen: optvalμ ν¬κΈ°μ
λλ€.
βοΈ getsockname
getsockname ν¨μλ μμΌμ λ‘컬 μ£Όμ μ 보λ₯Ό μ»μ΅λλ€. ν¨μμ νλ‘ν νμ
μ λ€μκ³Ό κ°μ΅λλ€.
#include <sys/types.h>
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *addr,
socklen_t *addrlen);
- sockfd: μμΌ νμΌ λμ€ν¬λ¦½ν°μ λλ€.
- addr: μμΌμ λ‘컬 μ£Όμ μ 보λ₯Ό μ μ₯ν sockaddr ꡬ쑰체μ ν¬μΈν°μ λλ€.
- addrlen: addrμ ν¬κΈ°μ λλ€. ν¨μλ₯Ό νΈμΆνκΈ° μ μ μ΄ κ°μ addrμ ν¬κΈ°λ‘ μ΄κΈ°νλμ΄μΌ ν©λλ€.
βοΈ getprotobyname
getprotobyname ν¨μλ νλ‘ν μ½ μ΄λ¦μ ν΄λΉνλ νλ‘ν μ½ λ²νΈλ₯Ό μ»μ΅λλ€. ν¨μμ νλ‘ν νμ
μ λ€μκ³Ό κ°μ΅λλ€.
#include <netdb.h>
struct protoent *getprotobyname(const char *name);
name: νλ‘ν μ½ μ΄λ¦μ λλ€. getprotobyname ν¨μλ struct protoent ꡬ쑰체μ ν¬μΈν°λ₯Ό λ°νν©λλ€. μ΄ κ΅¬μ‘°μ²΄μλ νλ‘ν μ½ μ΄λ¦, νλ‘ν μ½ λ²νΈ, νλ‘ν μ½μ λ©ν°μΊμ€νΈ μ£Όμ λ±μ μ λ³΄κ° μ μ₯λ©λλ€.
π getprotobynameμ μμλ₯Ό ν λ² λ³΄μ¬μ€. νλ‘ν μ½ λ²νΈλ μ΄λ»κ² μ»λ?
π° getprotobyname ν¨μλ νλ‘ν μ½ μ΄λ¦μ μ΄μ©νμ¬ struct protoent ꡬ쑰체λ₯Ό μ»μ΅λλ€. μ΄ κ΅¬μ‘°μ²΄μλ νλ‘ν μ½ μ΄λ¦, νλ‘ν μ½ λ²νΈ, νλ‘ν μ½μ λ©ν°μΊμ€νΈ μ£Όμ λ±μ μ λ³΄κ° μ μ₯λ©λλ€. λ°λΌμ getprotobyname ν¨μλ₯Ό μ¬μ©νλ©΄ νλ‘ν μ½ μ΄λ¦μ μ΄μ©νμ¬ νλ‘ν μ½ λ²νΈλ₯Ό μ»μ μ μμ΅λλ€.
λ€μμ getprotobyname ν¨μλ₯Ό μ¬μ©νμ¬ TCP νλ‘ν μ½μ λ²νΈλ₯Ό μ»λ μμμ λλ€.
#include <netdb.h>
#include <stdio.h>
int main() {
struct protoent *proto = getprotobyname("tcp");
if (proto == NULL) {
perror("getprotobyname");
return 1;
}
printf("Protocol name: %s\n", proto->p_name);
printf("Protocol number: %d\n", proto->p_proto);
printf("Aliases:\n");
for (char **alias = proto->p_aliases; *alias != NULL; alias++) {
printf("- %s\n", *alias);
}
return 0;
}
μ μμλ getprotobyname ν¨μλ₯Ό μ¬μ©νμ¬ tcp νλ‘ν μ½μ μ 보λ₯Ό μ»κ³ μΆλ ₯νλ μμμ λλ€. μ€ν κ²°κ³Όλ λ€μκ³Ό κ°μ΅λλ€.
Protocol name: tcp
Protocol number: 6
Aliases:
- tcp6
struct protoent ꡬ쑰체μ μ μ₯λ μ 보λ₯Ό μ΄μ©νμ¬ νλ‘ν μ½ λ²νΈλ₯Ό μ»μ μ μμ΅λλ€. μ μμμμλ proto->p_protoλ₯Ό μ΄μ©νμ¬ tcp νλ‘ν μ½μ λ²νΈμΈ 6μ μΆλ ₯νκ³ μμ΅λλ€.
π μ μμμμ aliasκ° λμ§ μλ €μ€λ³΄λ ΄
π°
struct protoent ꡬ쑰체μλ νλ‘ν μ½μ λν λ€μν μ 보λ€μ΄ ν¬ν¨λ©λλ€. p_aliases λ©€λ²λ ν΄λΉ νλ‘ν μ½μ λν λ³λͺ (alias)λ€μ λ°°μ΄μ κ°λ¦¬ν€λ ν¬μΈν°μ λλ€. μ¦, νλ‘ν μ½μ λν΄ μ¬λ¬ λ³λͺ μ΄ μ‘΄μ¬ν κ²½μ° μ΄ λ°°μ΄μ μ μ₯λ©λλ€.
μλ₯Ό λ€μ΄, getprotobyname("tcp") ν¨μλ₯Ό νΈμΆνμ¬ TCP νλ‘ν μ½μ μ 보λ₯Ό μ»μ κ²½μ° proto->p_aliases λ°°μ΄μλ "tcp6"κ³Ό κ°μ λ³λͺ μ΄ μ μ₯λ μ μμ΅λλ€. μ μμμμλ μ΄λ¬ν λ³λͺ (alias)λ€μ λ°λ³΅λ¬Έμ ν΅ν΄ μΆλ ₯νκ³ μμ΅λλ€.
π fcntl μ λν΄ μ€λͺ ν΄μ€ μ μκ² λ?
π°
fcntl ν¨μλ νμΌ λμ€ν¬λ¦½ν°μ λν μ μ΄λ₯Ό μννλ ν¨μμ λλ€. νμΌ λμ€ν¬λ¦½ν°μ λν μ¬λ¬κ°μ§ λμμ μνν μ μμΌλ©°, μ£Όλ‘ λ€μκ³Ό κ°μ λͺ©μ μΌλ‘ μ¬μ©λ©λλ€.
- νμΌ λμ€ν¬λ¦½ν°μ νλκ·Έ(μν)λ₯Ό λ³κ²½νκΈ° μν΄ μ¬μ©λ©λλ€. μλ₯Ό λ€μ΄, non-blocking λͺ¨λλ‘ νμΌ λμ€ν¬λ¦½ν°λ₯Ό μ€μ ν μ μμ΅λλ€.
- νμΌ λμ€ν¬λ¦½ν°μ μμ±μ λ³κ²½νκΈ° μν΄ μ¬μ©λ©λλ€. μλ₯Ό λ€μ΄, νμΌ λμ€ν¬λ¦½ν°μ close-on-exec νλκ·Έλ₯Ό μ€μ ν μ μμ΅λλ€.
- νμΌ λμ€ν¬λ¦½ν°λ₯Ό λκΈ°ννκΈ° μν΄ μ¬μ©λ©λλ€. μλ₯Ό λ€μ΄, νμΌ λμ€ν¬λ¦½ν°μ λ½(μ κΈ)μ μ€μ ν μ μμ΅λλ€.
fcntl ν¨μμ κΈ°λ³Έμ μΈ μ¬μ©λ²μ λ€μκ³Ό κ°μ΅λλ€.
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */);
- fd: νμΌ λμ€ν¬λ¦½ν°μ
λλ€.
- cmd: μνν λμμ μ§μ νλ μ μ΄ λͺ
λ Ήμ
λλ€.
- arg: μ μ΄ λͺ
λ Ήμ λ°λΌ μ¬μ©λ μΈμμ
λλ€.
- fcntl ν¨μλ μ μ΄ λͺ
λ Ήμ λ°λΌ arg μΈμκ° νμνμ§ μμ μλ μμ΅λλ€. λ°λΌμ arg μΈμλ κ°λ³ μΈμμ
λλ€.
μλ₯Ό λ€μ΄, λ€μμ νμΌ λμ€ν¬λ¦½ν°λ₯Ό non-blocking λͺ¨λλ‘ μ€μ νλ μμμ λλ€.
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int set_non_blocking(int fd) {
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
perror("fcntl(F_GETFL)");
return -1;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror("fcntl(F_SETFL)");
return -1;
}
return 0;
}
μ μμμμ fcntl(fd, F_GETFL, 0)λ₯Ό ν΅ν΄ νμΌ λμ€ν¬λ¦½ν° fdμ νλκ·Έλ₯Ό κ°μ Έμ€κ³ , μ΄λ₯Ό F_SETFL μ μ΄ λͺ λ Ήκ³Ό O_NONBLOCK νλκ·Έλ₯Ό μ΄μ©νμ¬ non-blocking λͺ¨λλ‘ μ€μ νκ³ μμ΅λλ€.
π fcntl(fd, F_SETFL, O_NONBLOCK) λΆλΆμ μλ―Έλ₯Ό μ’ λ μμΈνκ² μ€λͺ ν΄μ£Όλ ΄
π° fcntl(fd, F_SETFL, O_NONBLOCK)λ νμΌ λμ€ν¬λ¦½ν° fdλ₯Ό non-blocking λͺ¨λλ‘ μ€μ νλ μ½λμ λλ€.
μΌλ°μ μΌλ‘, νμΌ λμ€ν¬λ¦½ν°λ blocking λͺ¨λλ‘ λμν©λλ€. μ΄ λ§μ, νμΌ λμ€ν¬λ¦½ν°λ₯Ό μ½κ±°λ μΈ λ, ν΄λΉ μμ μ΄ μλ£λ λκΉμ§ λκΈ°νκ² λλ€λ λ»μ λλ€. μ΄λ¬ν λκΈ° μκ°μ μμ© νλ‘κ·Έλ¨μμ μ²λ¦¬ν λ€λ₯Έ μμ λ€μ μ§μ°μν€λ μμΈμ΄ λ μ μμ΅λλ€.
λ°λΌμ, non-blocking λͺ¨λλ‘ νμΌ λμ€ν¬λ¦½ν°λ₯Ό μ€μ νλ©΄, ν΄λΉ νμΌ λμ€ν¬λ¦½ν°λ₯Ό μ½κ±°λ μΈ λ, λκΈ°νμ§ μκ³ μ¦μ λ°ννκ² λ©λλ€. μ΄λ¬ν λμμ λκ° select, poll, epollκ³Ό κ°μ λΉλκΈ° μ μΆλ ₯ ν¨μμ ν¨κ» μ¬μ©λ©λλ€.
μμ μ½λμμ fcntl ν¨μλ fdμ λν μ μ΄ λͺ λ ΉμΌλ‘ F_SETFLμ μ§μ νκ³ , O_NONBLOCK νλκ·Έλ₯Ό μΆκ°νμ¬ non-blocking λͺ¨λλ‘ μ€μ νλλ‘ ν©λλ€. F_SETFLμ νμΌ λμ€ν¬λ¦½ν°μ νλκ·Έλ₯Ό μ€μ νκΈ° μν μ μ΄ λͺ λ Ή μ€ νλμ΄λ©°, O_NONBLOCKμ non-blocking λͺ¨λλ₯Ό λνλ΄λ μμμ λλ€.
λ°λΌμ fcntl(fd, F_SETFL, O_NONBLOCK)λ νμΌ λμ€ν¬λ¦½ν° fdλ₯Ό non-blocking λͺ¨λλ‘ μ€μ νλ μ½λμ λλ€.
π fcntl(fd, F_SETFL, O_NONBLOCK)μ μΈμ -1μ λ°ννλ
π° fcntl(fd, F_SETFL, O_NONBLOCK) ν¨μκ° -1μ λ°ννλ κ²½μ°λ μΌλ°μ μΌλ‘ λ€μκ³Ό κ°μ κ²½μ°μ λλ€.
- fdκ° μ ν¨νμ§ μμ νμΌ λμ€ν¬λ¦½ν°μΈ κ²½μ°
-
- F_SETFL λͺ
λ Ήμ΄ μ§μλμ§ μλ κ²½μ°
- F_SETFL λͺ
λ Ήμ΄ μ§μλμ§ μλ κ²½μ°
- O_NONBLOCK νλκ·Έκ° μ§μλμ§ μλ κ²½μ°
- λ€λ₯Έ νλ‘μΈμ€κ° μ΄λ―Έ fdλ₯Ό non-blocking λͺ¨λλ‘ μ€μ ν κ²½μ°
λν, fcntl() ν¨μκ° μ€ν¨νλ©΄ errno μ μ λ³μμ μ€ν¨ μμΈμ΄ μ μ₯λ©λλ€. λ°λΌμ, fcntl(fd, F_SETFL, O_NONBLOCK) ν¨μκ° -1μ λ°νν κ²½μ°, errno κ°μ νμΈνμ¬ μ€ν¨ μμΈμ νμ ν μ μμ΅λλ€.
π fcntl μΌλ‘ μ¬λ¬ νμΌ λμ€ν¬λ¦½ν°λ₯Ό non-blocking λͺ¨λλ‘ μ€μ νκ³ μ€ννλ μμλ₯Ό 보μ¬μ€ μ μκ² λ?
π°
λ€, λΉμ°νμ! μλ μμ μ½λλ νμΌ λμ€ν¬λ¦½ν° 0, 1, 2λ₯Ό non-blocking λͺ¨λλ‘ μ€μ ν ν, select() ν¨μλ₯Ό μ¬μ©νμ¬ κ° νμΌ λμ€ν¬λ¦½ν°μμ μ λ ₯μ λ°μλ€μ΄λ μμμ λλ€.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
int main()
{
// νμΌ λμ€ν¬λ¦½ν° 0, 1, 2λ₯Ό non-blocking λͺ¨λλ‘ μ€μ
int fd_flags;
for (int i = 0; i < 3; i++) {
fd_flags = fcntl(i, F_GETFL, 0);
if (fd_flags == -1) {
perror("fcntl");
exit(1);
}
if (fcntl(i, F_SETFL, fd_flags | O_NONBLOCK) == -1) {
perror("fcntl");
exit(1);
}
}
fd_set readfds;
char buf[1024];
while (1) {
// select() ν¨μλ₯Ό μ¬μ©νμ¬ μ
λ ₯μ λ°μλ€μ
FD_ZERO(&readfds);
FD_SET(0, &readfds);
FD_SET(1, &readfds);
FD_SET(2, &readfds);
if (select(3, &readfds, NULL, NULL, NULL) == -1) {
perror("select");
exit(1);
}
// μ
λ ₯μ΄ λ€μ΄μ¨ νμΌ λμ€ν¬λ¦½ν°μμ λ°μ΄ν°λ₯Ό μ½μ
for (int i = 0; i < 3; i++) {
if (FD_ISSET(i, &readfds)) {
ssize_t nread = read(i, buf, sizeof(buf));
if (nread == -1) {
perror("read");
exit(1);
}
printf("fd=%d, read %zd bytes: %.*s\n", i, nread, (int)nread, buf);
}
}
}
return 0;
}
μ μ½λμμλ λ¨Όμ νμΌ λμ€ν¬λ¦½ν° 0, 1, 2λ₯Ό non-blocking λͺ¨λλ‘ μ€μ νκ³ μμ΅λλ€. κ·Έ λ€μμλ select() ν¨μλ₯Ό μ¬μ©νμ¬ νμΌ λμ€ν¬λ¦½ν°μμ μ λ ₯μ λ°μλ€μ΄κ³ , μ λ ₯μ΄ λ€μ΄μ¨ νμΌ λμ€ν¬λ¦½ν°μμ λ°μ΄ν°λ₯Ό μ½μ΄ μΆλ ₯ν©λλ€.
μ°Έκ³ λ‘, μ μ½λμμλ νμΌ λμ€ν¬λ¦½ν° 0, 1, 2λ₯Ό λμμΌλ‘ non-blocking λͺ¨λλ₯Ό μ€μ νκ³ μμ§λ§, μ€μ λ‘λ μ΄ μΈμλ λ€λ₯Έ νμΌ λμ€ν¬λ¦½ν°μ λν΄μλ non-blocking λͺ¨λλ₯Ό μ€μ ν μ μμ΅λλ€.
π select(3, &readfds, NULL, NULL, NULL) μ μΈμμ λν΄ μ€λͺ ν΄μ£Όλ ΄^^
π° select() ν¨μλ I/O λ©ν°νλ μ±μ μννκΈ° μν μμ€ν μ½ μ€ νλλ‘, μ¬λ¬ κ°μ νμΌ λμ€ν¬λ¦½ν°μμ λ°μ΄ν°λ₯Ό μ½κ³ μ°λ μμ μ ν λ²μ μ²λ¦¬ν μ μκ² ν΄μ€λλ€. select() ν¨μλ λ€μκ³Ό κ°μ ννλ₯Ό κ°μ§κ³ μμ΅λλ€.
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
- nfds: κ²μ¬ν νμΌ λμ€ν¬λ¦½ν° μ(+1 λ μ΅λκ°)
- readfds: μ½κΈ° κ°λ₯ν μνλ₯Ό κ²μ¬ν νμΌ λμ€ν¬λ¦½ν° μ§ν©
- writefds: μ°κΈ° κ°λ₯ν μνλ₯Ό κ²μ¬ν νμΌ λμ€ν¬λ¦½ν° μ§ν©
- exceptfds: μμΈκ° λ°μν μνλ₯Ό κ²μ¬ν νμΌ λμ€ν¬λ¦½ν° μ§ν©
- timeout: select() ν¨μκ° λΈλ‘νΉλλ μκ°μ μ§μ νλ κ°. NULLμ΄λ©΄ 무νμ λΈλ‘νΉλλ€.
μμ ν¨μ νΈμΆμμλ readfdsλ§ μ§μ νκ³ λλ¨Έμ§ μΈμλ€μ NULLμ μ λ¬νμμ΅λλ€. μ΄λ readfds μ§ν©μ λ±λ‘λ νμΌ λμ€ν¬λ¦½ν° μ€μμ μ½μ μ μλ κ²μ΄ μλμ§λ₯Ό κ²μ¬νκ³ μ νκΈ° λλ¬Έμ λλ€. μ΄μ κ°μ΄ κ²μ¬ν I/O μνλ₯Ό μ€μ νλ λΆλΆμ λ€μκ³Ό κ°μ λ°©λ²μΌλ‘ μ΄λ£¨μ΄μ§λλ€.
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd1, &readfds);
FD_SET(fd2, &readfds);
λ¨Όμ fd_set νμ μ λ³μ readfdsλ₯Ό μ μΈνκ³ , FD_ZERO() ν¨μλ₯Ό μ¬μ©νμ¬ readfds μ§ν©μ λͺ¨λ λΉνΈλ₯Ό 0μΌλ‘ μ΄κΈ°νν©λλ€. κ·Έλ¦¬κ³ FD_SET() ν¨μλ₯Ό μ¬μ©νμ¬ fd1κ³Ό fd2λΌλ λ κ°μ νμΌ λμ€ν¬λ¦½ν°λ₯Ό readfds μ§ν©μ λ±λ‘ν©λλ€.
select() ν¨μλ μ§μ λ νμΌ λμ€ν¬λ¦½ν° μ€ νλ μ΄μμ I/O μν λ³νκ° λ°μν λκΉμ§ λΈλ‘νΉλλ©°, I/O μν λ³νκ° λ°μνλ©΄ ν΄λΉ μνλ₯Ό κ²μ¬ν ν readfdsμ λ±λ‘λ νμΌ λμ€ν¬λ¦½ν° μ€μμ μ½μ μ μλ κ²μ΄ μλμ§λ₯Ό κ²μ¬νμ¬ μ½κΈ° κ°λ₯ν μνλ₯Ό νμΈν©λλ€. λ°λΌμ, select() ν¨μ νΈμΆ μ΄νμλ readfdsμ μ€μ λ νμΌ λμ€ν¬λ¦½ν° μ€μμ μ½κΈ° κ°λ₯ν μνμΈ κ²μ΄ μμΌλ©΄ κ·Έ νμΌ λμ€ν¬λ¦½ν°λ₯Ό μ΄μ©νμ¬ λ°μ΄ν°λ₯Ό μ½μ μ μκ² λ©λλ€.
π μ μμμμ λ±μ₯νλ FD_ZERO(&readfds), FD_SET(0, &readfds), FD_ISSET(i, &readfds)λ€μ ν¨μλ?
π° λ€, λ§μ΅λλ€.
- FD_ZERO(&readfds): readfds μ§ν©μ μ΄κΈ°ννλ ν¨μμ
λλ€. readfds μ§ν© λ΄μ λͺ¨λ νμΌ λμ€ν¬λ¦½ν°λ₯Ό μ κ±°νκ³ μ΄κΈ° μνλ‘ λ§λλλ€.
- FD_SET(0, &readfds): νμΌ λμ€ν¬λ¦½ν° 0μ readfds μ§ν©μ μΆκ°νλ ν¨μμ
λλ€. μ΄ κ²½μ° νμΌ λμ€ν¬λ¦½ν° 0μ νμ€ μ
λ ₯μ λνλ
λλ€.
- FD_ISSET(i, &readfds): νμΌ λμ€ν¬λ¦½ν° iκ° readfds μ§ν©μ ν¬ν¨λμ΄ μλμ§ μ¬λΆλ₯Ό νμΈνλ ν¨μμ
λλ€. λ°νκ°μ 0 λλ 1μ
λλ€.
π fdκ° μ½μ μ μλ μνμΈμ§ κ²μ¦νλ μ½λμ μμλ₯Ό 보μ¬μ£Όλ ΄^^
π°
fdκ° μ½μ μ μλ μνμΈμ§ κ²μ¦νλ μ½λλ λ€μκ³Ό κ°μ΄ μμ±ν μ μμ΅λλ€.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
int main(void) {
fd_set rfds;
struct timeval tv;
int retval;
// νμΌ λμ€ν¬λ¦½ν° 0μ λͺ¨λν°λ§νκΈ° μν΄ rfds μ§ν© μ΄κΈ°ν
FD_ZERO(&rfds);
FD_SET(0, &rfds);
// νμ΄λ¨Έ μ€μ
tv.tv_sec = 5;
tv.tv_usec = 0;
// νμΌ λμ€ν¬λ¦½ν° 0μ΄ μ½μ μ μλ μνκ° λ λκΉμ§ λκΈ°
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
perror("select()");
exit(EXIT_FAILURE);
} else if (retval) {
printf("Data is available now.\n");
} else {
printf("No data within five seconds.\n");
}
return 0;
}
μ μ½λμμ FD_ZERO ν¨μλ₯Ό μ¬μ©νμ¬ rfds μ§ν©μ μ΄κΈ°νν©λλ€. κ·Έλ¦¬κ³ FD_SET ν¨μλ₯Ό μ¬μ©νμ¬ νμΌ λμ€ν¬λ¦½ν° 0 (νμ€ μ λ ₯)μ rfds μ§ν©μ μΆκ°ν©λλ€. μ΄μ select ν¨μλ₯Ό νΈμΆνμ¬ rfds μ§ν©μ ν¬ν¨λ νμΌ λμ€ν¬λ¦½ν° μ€μμ μ½μ μ μλ μνκ° λκΈ°λ₯Ό κΈ°λ€λ¦½λλ€. select ν¨μμ λ§μ§λ§ μΈμ &tvλ select ν¨μκ° μ΅λ λͺ μ΄ λμ λκΈ°ν΄μΌ νλμ§λ₯Ό μ§μ ν©λλ€. select ν¨μλ rfds μ§ν©μ μλ νμΌ λμ€ν¬λ¦½ν° μ€μμ μ½μ μ μλ μνκ° λλ©΄ 1μ λ°νν©λλ€. λ§μ½ νμμμμ΄ λ°μνλ©΄ 0μ λ°νν©λλ€. κ·Έλ¦¬κ³ μλ¬κ° λ°μνλ©΄ -1μ λ°ννκ³ perror ν¨μλ₯Ό νΈμΆνμ¬ μλ¬ λ©μμ§λ₯Ό μΆλ ₯ν©λλ€.