π 곡λΆνλ μ§μ§μνμΉ΄λ μ²μμ΄μ§?
[리λ μ€ λ€νΈμν¬ νλ‘κ·Έλλ°] TCPμλ²μ ν΄λΌμ΄μΈνΈ νλ‘κ·Έλλ° λ³Έλ¬Έ
[리λ μ€ λ€νΈμν¬ νλ‘κ·Έλλ°] TCPμλ²μ ν΄λΌμ΄μΈνΈ νλ‘κ·Έλλ°
μ§μ§μνμΉ΄ 2024. 1. 31. 12:37<μμμ§ λμ μ¬λ¬ΌμΈν°λ·μ μν 리λ μ€ νλ‘κ·Έλλ° with λΌμ¦λ² 리νμ΄ μμ μ μ°Έκ³ ν΄μ μμ±νμμ΅λλ€ :-)>
β TCP
TCP λ μ°κ²° κΈ°λ°μ μ λ’°μ±μ΄ μλ ν΅μ λ°©μμΌλ‘ FTP, λ©μΌ, μΉ μλΉμ€ λ± μΈν°λ·μ μ΄μ©ν λ€μν μλΉμ€μμ μ¬μ©λκ³ μλ€
TCP λ μ£Όλ‘ μλ²μ ν΄λΌμ΄μΈνΈ κ° ν΅μ λ°©μμ΄λ€
TCP μλ²λ μμΌμ μμ±ν ν λ°μΈλ (bind) νλ κ³Όμ μ UDP κ³Όμ κ³Ό λμΌνλ€
butπ¨ UDPμ λ€λ₯΄κ² TCP λ ν΄λΌμ΄μΈνΈκ° 3 Way-Handshaking (connect() ν¨μ) λ₯Ό ν΅ν΄μ μλ²μ μ μνκΈ° λλ¬Έμ ν΄λΌμ΄μΈνΈμ λκΈ°λ₯Ό μ²λ¦¬νκΈ° μν ν (queue) κ° νμνλ€
μ΄λ₯Ό μν΄ listen() ν¨μλ₯Ό ν΅ν΄ λκΈ° νλ₯Ό μ€μ νκ³ , accept() ν¨μλ₯Ό ν΅ν΄ ν΄λΌμ΄μΈνΈμ μ μμ κΈ°λ€λ¦΄ μ μλ€
TCP ν΄λΌμ΄μΈνΈλ λ¨Όμ μμΌμ μμ±νκ³ μλ²μ μ μμ ν΄μΌνλλ°, connect() ν¨μλ₯Ό μ΄μ©νλ€
μλ²μ μ μλ νμλ read() λ write() ν¨μλ₯Ό ν΅ν΄ ν΅μ μ μ§νν΄λ λκ³ , recv()λ send() ν¨μλ₯Ό μ¬μ©ν΄λ λλ€
UDP μ λ¬λ¦¬, μ΄λ―Έ μλ²μ μ μν΄ μμΌλ―λ‘ λ°μ΄ν°λ₯Ό λ³΄λΌ λ μλ²μ μ 보λ₯Ό μ¬μ©ν νμκ° μλ€
TCPλ UDP μ κ°μ΄ κ΄λ ¨ ν΅μ μμ μ΄ μλ£λλ©΄ close() ν¨μλ₯Ό λΆλ¬μ μμΌμ λ«μμ£Όλ©΄ λλ€
β TCP ν΄λΌμ΄μΈνΈ
TCP ν΄λΌμ΄μΈνΈλ μμΌμ λ§λ νμ TCP μλ²μ μ μν΄μΌ νλ€
connect() ν¨μλ₯Ό μ΄μ©νμ¬ μλ²μ μ μνκ³ , write()λ send() ν¨μλ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό 보λ΄λ©° read()λ recv() ν¨μλ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό λ°μ μ μλ€
μλ²μμ ν΅μ μ΄ λλλ©΄ close() ν¨μλ₯Ό μ΄μ©ν΄μ μ΄μλ μμΌμ λ«λλ€
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
connect() ν¨μλ μλ²μ μμΌμ μ°κ²°νλ©°, μλ²μμ μ°κ²°μ μ±κ³΅νλ©΄ 0μ λ°ννκ³ , μλ² μμΌμ΄ μ‘΄μ¬νμ§ μκ±°λ μμΌ νκ° κ°λ μ°¨ μμΌλ©΄ -1μ λ°ννλ€
μμΌμ νμΌ λμ€ν¬λ¦½ν°λ‘ μ·¨κΈλκΈ° λλ¬Έμ read(), write() ν¨μλ₯Ό ν΅ν΄μ λ°μ΄ν°λ₯Ό μ½κ±°λ λ³΄λΌ μ μμΌλ©°, recv()λ send() ν¨μλ₯Ό μ΄μ©ν΄ ν΅μ μ μνν μ μλ€
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
sszie_T send(int sockfd, const void * buf, size_T len, int flags);
β TCP μλ²
TCP μλ²λ TCP ν΄λΌμ΄μΈνΈμμ ν΅μ μ μν΄ μμΌμ μμ±ν ν, bind() ν¨μλ₯Ό μ¬μ©νμ¬ μ΄μ체μ (컀λ)μ μλΉμ€λ₯Ό μ°κ²°ν¨μΌλ‘μ¨ μλ²λ‘ μ μνλ ν΄λΌμ΄μΈνΈμ λ°μ΄ν°λ₯Ό λ°μ μ μλλ‘ μ€λΉνλ€
ν΄λΌμ΄μΈνΈ μλΉμ€μ μ€λΉκ° μλ£λλ©΄ μλ²μμ ν΄λΌμ΄μΈνΈμ μ μμ μ²λ¦¬ν΄μΌ ν λ©λͺ¨λ¦¬ 곡κ°μ΄ νμνκ² λλ€
μ΄λ listen() ν¨μλ₯Ό μ΄μ©ν΄μ μ°κ²° μμ²μ μν λκΈ° νλ₯Ό μ€μ ν μ μλ€
int listen(int sockfd, int backlog);
lisetn() ν¨μλ μ°κ²° μμ²μ ν μ μλ μμΌμ μ΅λ μλ₯Ό λͺ μνλ©°, μ΄ μλ₯Ό λμ΄μλ ν΄λΌμ΄μΈνΈμ μ°κ²° μλλ κ±°λΆλλ€
μλ²μμ ν΄λΌμ΄μΈνΈμ μ°κ²°μ λν κ³΅κ° (λκΈ° ν)λ₯Ό ν보ν νμλ ν΄λΌμ΄μΈνΈμ μ°κ²°μ λκΈ°ν΄μΌ νλλ°, accept() ν¨μλ₯Ό μ΄μ©ν μ μλ€
accept() ν¨μλ₯Ό ν΅ν΄μ μλ²μ ν΄λΌμ΄μΈνΈκ° μ°κ²°λλ©΄ ν΄λΌμ΄μΈνΈμ ν΅μ ν μ μλ μμΌμ λν νμΌ λμ€ν¬λ¦½ν°κ° λ°νλλ€
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
accept() ν¨μμλ μ μν ν΄λΌμ΄μΈνΈμ μ 보λ₯Ό μ»κΈ° μν΄ μ£Όμ ꡬ쑰체λ₯Ό μ¬μ©νλ€
μ£Όμ ꡬ쑰체 νλ μ€ IPμ ν¬νΈλ λΉ μλμμΌλ‘ μ¬μ©λκΈ° λλ¬Έμ μΈμ½λ© λ³νμ΄ νμν μ μλ€
ν΄λΌμ΄μΈνΈμ μ μμ΄ μ΄λ€μ§λ©΄ ν΄λΌμ΄μΈνΈμμ ν΅μ μ μν μλ‘μ΄ ν¬νΈ λ²νΈκ° λ°νλλ©° μ΄λ₯Ό ν΅ν΄ μλ²μ ν΄λΌμ΄μΈνΈ κ° ν΅μ μ μ²λ¦¬ν μ μλ€
// tcp_server.c
// TCP μμΌ κΈ°λ°μ ν΅μ
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define TCP_PORT 5100 /* μλ²μ ν¬νΈ λ²νΈ */
int main(int argc, char **argv)
{
int ssock; /* μμΌ λμ€ν¬λ¦½νΈ μ μ */
socklen_t clen;
int n;
struct sockaddr_in servaddr, cliaddr; /* μ£Όμ ꡬ쑰체 μ μ */
char mesg[BUFSIZ];
/* μλ² μμΌ μμ± */
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(TCP_PORT); /* μ¬μ©ν ν¬νΈ μ§μ */
/* bind ν¨μλ₯Ό μ¬μ©νμ¬ μλ² μμΌμ μ£Όμ μ€μ */
if(bind(ssock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind()");
return -1;
}
/* λμμ μ μνλ ν΄λΌμ΄μΈνΈμ μ²λ¦¬λ₯Ό μν λκΈ° νλ₯Ό μ€μ */
if(listen(ssock, 8) < 0) {
perror("listen()");
return -1;
}
clen = sizeof(cliaddr);
do {
/* ν΄λΌμ΄μΈνΈκ° μ μνλ©΄ μ μμ νμ©νκ³ ν΄λΌμ΄μΈνΈ μμΌ μμ± */
int n, csock = accept(ssock, (struct sockaddr *)&cliaddr, &clen);
/* λ€νΈμν¬ μ£Όμλ₯Ό λ¬Έμμ΄λ‘ λ³κ²½ */
inet_ntop(AF_INET, &cliaddr.sin_addr, mesg, BUFSIZ);
printf("Client is connected : %s\n", mesg);
if((n = read(csock, mesg, BUFSIZ)) <= 0)
perror("read()");
printf("Received data : %s", mesg);
/* ν΄λΌμ΄μΈνΈλ‘ bufμ μλ λ¬Έμμ΄ μ μ‘ */
if(write(csock, mesg, n) <= 0)
perror("write()");
close(csock); /* ν΄λΌμ΄μΈνΈ μμΌμ λ«μ */
} while(strncmp(mesg, "q", 1));
close(ssock); /* μλ² μμΌμ λ«μ */
return 0;
}
/*
μλ²λ ν΄λΌμ΄μΈνΈλ‘λΆν° λ°μ΄ν°λ₯Ό λ°μμ κ·Έλλ‘ λ³΄λ΄μ£Όλ TCP κΈ°λ°μ μμ½ μλ²
socket() ν¨μμ SOCK_STREAM μ΅μ
μ μ¬μ©νμ¬ TCP μ© μμΌ λμ€ν¬λ¦½ν°λ₯Ό μ°λ€
UDPμ λ§μ°¬κ°μ§λ‘ ν΄λΉ νλ‘κ·Έλ¨μ μλ²λ‘ μ¬μ©νκΈ° μν΄μλ bind() ν¨μλ₯Ό μ΄μ©νμ¬ μ΄μ체μ μ μλΉμ€λ₯Ό λ±λ‘ν΄μΌ νκ³ ,
bind() ν¨μμ λ λ²μ§Έ μΈμλ‘ μλ² μμ μ IP μ£Όμλ₯Ό μ¬μ©ν΄μΌ νλ€
μ½κ² μ²λ¦¬νκΈ° μν΄ INADDR_ANY λ₯Ό μ¬μ©νμλλ°, μλ²μ IP μ£Όμλ₯Ό μλμΌλ‘ μ°Ύμμ μ±μμ€λ€
ν΄λΌμ΄μΈνΈμ ν΅μ μ μν ν¬νΈ λ²νΈλ μ€μ νμλ€
ν΄λΌμ΄μΈνΈμ μμΌλ€μ μν΄ λκΈ° νλ₯Ό μ€μ ν΄μΌ νλ€. listen() ν¨μλ₯Ό μ΄μ©ν΄μ μ΅λ 8λμ ν΄λΌμ΄μΈνΈκ° λμ μ μ λκΈ°λ₯Ό ν μ μλλ‘ μ€μ νμλ€
μμΌ νμ μ€μ μ΄ λλλ©΄ ν΄λΌμ΄μΈνΈμ μ μμ κΈ°λ€λ €μΌ νλλ°, accept() ν¨μλ₯Ό μ¬μ©ν μ μλ€
μ μν ν΄λΌμ΄μΈνΈμ λν μ 보λ λ λ²μ§Έ μΈμλ‘ μ λ¬λλ©°, inet_ntop() λ±μ ν¨μλ‘ μ¬λμ΄ μ½μ μ μλ λ¬Έμ κΈ°λ°μ μ£Όμ μ€νΈλ¦ΌμΌλ‘ λ³νν΄μ μΆλ ₯ν μ μλ€
μ€μ ν΄λΌμ΄μΈνΈμ ν΅μ μ accpet() ν¨μλ‘ λ°νλλ μμΌ λμ€ν¬λ¦½ν°λ₯Ό μ΄μ©νκ³ read() / recv() μ write() / send() κ°μ ν¨μλ₯Ό μ΄μ©ν΄μ ν΅μ μ μ§νν μ μλ€
ν΅μ μμ
μ΄ λλλ©΄ close() ν¨μλ‘ μ μλ ν΄λΌμ΄μΈνΈμ μλ²μ μμΌμ κ°κ° λ«λλ€
*/
// tcp_client.c
// TCP μμΌ κΈ°λ°μ ν΅μ
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define TCP_PORT 5100
int main(int argc, char **argv)
{
int ssock;
struct sockaddr_in servaddr;
char mesg[BUFSIZ];
if(argc < 2) {
printf("Usage : %s IP_ADRESS\n", argv[0]);
return -1;
}
/* μμΌμ μμ± */
if((ssock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket()");
return -1;
}
/* μμΌμ΄ μ μν μ£Όμ μ§μ */
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
/* λ¬Έμμ΄μ λ€νΈμν¬ μ£Όμλ‘ λ³κ²½ */
inet_pton(AF_INET, argv[1], &(servaddr.sin_addr.s_addr));
servaddr.sin_port = htons(TCP_PORT);
/* μ§μ ν μ£Όμλ‘ μ μ */
if(connect(ssock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("connect()");
return -1;
}
fgets(mesg, BUFSIZ, stdin);
if(send(ssock, mesg, BUFSIZ, MSG_DONTWAIT) <= 0) { /* λ°μ΄ν°λ₯Ό μμΌμ μ΄λ€. */
perror("send()");
return -1;
}
memset(mesg, 0, BUFSIZ);
if(recv(ssock, mesg, BUFSIZ, 0) <= 0) { /* λ°μ΄ν°λ₯Ό μμΌμΌλ‘λΆν° μ½λλ€. */
perror("recv()");
return -1;
}
printf("Received data : %s", mesg); /* λ°μμ¨ λ¬Έμμ΄μ νλ©΄μ μΆλ ₯ */
close(ssock); /* μμΌμ λ«λλ€. */
return 0;
}
/*
ν΄λΌμ΄μΈνΈμμλ TCP μ© μμΌμ μμ±ν ν connect() ν¨μλ₯Ό μ¬μ©νμ¬ μλ²μ μ μνλ€
connect() ν¨μμλ μλ² μ£Όμμ λν μ 보λ₯Ό λͺ
μνλ€
κΈ°λ³Έμ μΈ μ£Όμ μ€μ λ°©λ²μ bind() ν¨μμ λμΌνμ§λ§, connect() ν¨μλ INADDR_ANY λ₯Ό μ¬μ©ν μ μλ€ (ν¬νΈ λ²νΈλ μλ²μ κ°μ λ²νΈλ₯Ό μ¬μ©)
μλ²μ μ μν ν fgets() ν¨μλ₯Ό μ΄μ©ν΄μ ν€λ³΄λλ‘ λ°μ΄ν°λ₯Ό λ°μλ€μΈ ν, μμμ μμ±ν μμΌμ μ΄μ©νμ¬ send() λ write() ν¨μλ₯Ό ν΅ν΄ μλ²λ‘ λ°μ΄ν°λ₯Ό 보λ΄κ³ ,
resv() λ read() ν¨μλ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό λ°λλ€. printf() ν¨μλ₯Ό μ΄μ©ν΄μ μλ²λ‘λΆν° λ°μ λ°μ΄ν°λ₯Ό νλ©΄μ νμνμλ€
μμ μ½λλ₯Ό λΉλνκ³ λ¨Όμ μλ²λ₯Ό μ€νμν¨λ€. UDP μ λ§μ°¬κ°μ§λ‘ ν΄λΌμ΄μΈνΈλ₯Ό ν¨κ» μ€ννλ €λ©΄ λ€λ₯Έ ν°λ―Έλμ΄ νμνλ―λ‘ λ€λ₯Έ ν°λ―Έλμ μ΄κ³ λ‘κ·ΈμΈ OR μλ²λ₯Ό λ°±κ·ΈλΌμ΄λλ‘ γ
£γΉν
κ°μ λΌμ¦λ² 리νμ΄/PC μμ μ€νλκ³ μλ μλ²λ‘ μ μν λλ μλ²μ 127.0.0.1μ μ
λ ₯νλ€
ν΄λΌμ΄μΈνΈμμ λ¬Έμμ΄μ μ
λ ₯νλ©΄ TCP λ₯Ό ν΅ν΄μ ν΄λΌμ΄μΈνΈμ μλ² κ°μ ν΅μ μ΄ μ΄λ€μ§λ€
ν΄λΌμ΄μΈνΈλ λ¨Όμ μλ²λ‘ λ¬Έμμ΄μ 보λ΄λ©΄ μλ²μμλ λ¬Έμμ΄μ μ½κ³ λ€μ ν΄λΌμ΄μΈνΈμκ² λλλ €μ€λ€
ν΄λΌμ΄μΈνΈλ μλ²λ‘λΆν° μ λ¬λ λ°μ΄ν°λ₯Ό λ°μμ νλ©΄μ μΆλ ₯νκ³ μλ²λ₯Ό μ’
λ£νκ³ μΆμ λλ ν΄λΌμ΄μΈνλ₯΄ μμνκ³ q λ₯Ό μ
λ ₯νλ©΄ λλ€
*/
gcc -o tcp_server tcp_server.c
gcc -o tcp_client tcp_client.c
./tcp_server &
./tcp_client 127.0.0.1
β μ°μν μ°κ²° μ’ λ£: shutdown() ν¨μ
close() ν¨μλ₯Ό μ¬μ©νλ©΄ μλ²μμμ μ½κΈ° / μΆλ ₯ μ© μμΌμ λͺ¨λ λ«λλ€
shutdown() ν¨μλ₯Ό μ¬μ©νλ©΄ κ²½μ°μ λ°λΌ μ½κΈ° μμΌλ§ λ«κ±°λ, μ°κΈ° μμΌλ§ λ«μ μ μλ€
int shutdown(int sockfd, int how);
shutdown() ν¨μμ λ λ²μ§Έ μΈμ(how) λ₯Ό ν΅ν΄ μ½κ±°λ μ°κΈ° νΉμ μ½κΈ°/μ°κΈ° μ© μμΌμ λͺ¨λ λ«μ μ μλ€
shutdown() ν¨μμ SHUT_RDWR μ μ΄μ©νλ©΄ close() ν¨μμ²λΌ μ /μΆλ ₯ μ€νΈλ¦Όμ λͺ¨λ λ«λλ°, close() ν¨μμ λ¬λ¦¬ λ³λ€λ₯Έ μμ μμ΄ λ°λ‘ μ’ λ£μν¨λ€
μμ«κ° | λͺ¨λ | λ΄μ© |
0 | SHUT_RD | μ λ ₯ μ€νΈλ¦Ό μ’ λ£ |
1 | SHUT_WR | μΆλ ₯ μ€νΈλ¦Ό μ’ λ£ |
2 | SHUT_RDWR | μ /μΆλ ₯ μ€νΈλ¦Ό μ’ λ£ |
ν΄λΌμ΄μΈνΈ μ½λμμλ λ°μ΄ν°λ₯Ό λ΄λ³΄λΈ νμ shutdown() ν¨μλ₯Ό μ΄μ©ν΄ μμΌμ μ°κΈ° μ€νΈλ¦Όμ λ«κ³ (SHUT_WR), λ°μ΄ν°λ₯Ό μ½μ νμλ μμΌ μ½κΈ° μ€νΈλ¦Όμ λ«μ μ μλ€ (SHUT_RD)