From cf8e69d49ab77f8d4b09c8bc1c73bd4e6fd91285 Mon Sep 17 00:00:00 2001 From: qzzloz Date: Thu, 11 Apr 2024 00:18:12 +0900 Subject: [PATCH 1/2] =?UTF-8?q?workbook:=20chapter1=20=EC=9B=8C=ED=81=AC?= =?UTF-8?q?=EB=B6=81=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/chapter1/Ch01Keyword.md | 135 +++++++++++++++++++++++++++++++++ src/practice/chapter1/client.c | 36 +++++++++ src/practice/chapter1/server.c | 59 ++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 docs/chapter1/Ch01Keyword.md create mode 100644 src/practice/chapter1/client.c create mode 100644 src/practice/chapter1/server.c diff --git a/docs/chapter1/Ch01Keyword.md b/docs/chapter1/Ch01Keyword.md new file mode 100644 index 0000000..da8abb5 --- /dev/null +++ b/docs/chapter1/Ch01Keyword.md @@ -0,0 +1,135 @@ +# Ch01. Server (Socket & Multi-Process) +1주차 워크북 - 서버란 무엇인가(소켓&멀티 프로세스) + +
+ +# TCP +[TCP 공식문서](https://www.rfc-editor.org/rfc/rfc793) + +TCP란 서버와 클라이언트 간 데이터를 송/수신을 위한 프로토콜이다. + +TCP의 특징 +1. reliable data +2. connection-oriented(3-way handshake) +3. in-order data +4. congestion control +5. flow control +6. 양방향 전송 +7. 1:1통신 (unicast) 등 + +TCP 소켓은 source의 IP, port와 destination의 IP, port로 구분한다. +
+
+ +# UDP + +[UDP 공식문서](https://www.rfc-editor.org/rfc/rfc768.txt) + +속성 +1. unreliable data +2. out-of-order → 순서가 뒤바뀐채 전달될 가능성O +3. 비연결성 +4. checksum +5. 단방향 통신 +6. 속도 빠름 + +UDP 소켓은 source의 IP, destination의 IP로 구분한다. +
+
+ +# 시스템 콜? +응용프로그램이 요청할 때 커널에 접근할 수 있는 인터페이스이다. 파일을 읽어오거나 파일을 쓰거나 화면에 메시지를 출력하는 등의 서비스를 수행하기 위해 OS는 하드웨어를 직접 관리한다. 반면 응용프로그램은 OS가 제공하는 인터페이스를 통해서만 자원을 사용할 수 있는데, OS가 제공하는 인터페이스를 시스템콜 이라고 한다. + +운영체제가 하드웨어, CPU를 사용하는 모드를 커널 모드라고 한다. 애플리케이션 코드를 실행하는 모드를 사용자 모드라고 한다. 사용자 모드에서 하드웨어 자원에 접근하기 위해서는(=커널 영역의 기능을 사용하기 위해서는) 시스템 콜을 사용해야 한다. + +보통 API를 통해 사용한다. + +[Ref](https://didu-story.tistory.com/311) +
+
+ +# 하드웨어 인터럽트 +CPU 외의 장치에서 예외상황이 발생하여 처리가 필요한 경우에 컨트롤러가 인터럽트 신호를 발생시켜 CPU에게 알리는 것을 말한다. + +하드웨어 장치가 CPU에게 어떤 사실을 알려주거나 CPU의 서비스를 요청해야 하는 경우, "인터럽트 발생~" 하면서 인터럽트 라인을 세팅한다. 다른 명령을 수행하고 있던 CPU는 인터럽트 라인을 확인하면 하던 일을 멈추고 인터럽트를 처리하러 간다. + +- **인터럽트 벡터** + +인터럽트가 발생하면 CPU는 운영체제에게 제어권을 주고 인터럽트 처리를 위해 정의된 코드(=루트)를 찾는다. 운영체제는 인터럽트가 발생하면 정의된 코드를 찾을 수 있도록 처리해야 할 루틴의 주소를 보관하고 있는 테이블을 갖고 있다. 이 테이블을 인터럽트 벡터라고 한다. + +- **인터럽트 핸들러** + +운영체제 커널은 인터럽트가 들어왔을 때 처리해야 할 코드를 포함하고 있다.(이미 프로그래밍 되어 있다!~) 이 코드를 인터럽트 처리루틴(ISR), 인터럽트 핸들러라고 한다. + +[Ref](https://baebalja.tistory.com/354) + +
+
+ +# 리눅스의 파일과 파일 디스크립터 +- 리눅스의 파일 + +리눅스는 모든 것을 파일로 취급한다. 디렉토리, 소켓 등등 모든 것을 파일로 관리한다. + +- 파일 디스크립터 + +리눅스에서 파일을 다룰 때 사용하는 개념이다. 프로세스에서 특정 파일에 접근할 때 사용하는 추상적인 값이다. stdin(표준입력, 0), stdout(표준출력, 1), stderr(표준에러, 2)는 이미 파일 디스크립터 값이 할당되어 있기 때문에 3 이상부터 사용할 수 있다. + +리눅스에서 프로세스가 소켓에 접근한다면, 소켓은 파일이므로 파일 디스크립터를 이용할 것이다. +
+
+ +# socket() 시스템 콜 +새로운 소켓을 생성하고 파일 디스크립터를 반환한다. + + socket(domain, type, protocol) +- domain: IPv4는 AF_INET, IPv6는 AF_INET6 +- type: TCP 소켓인 경우 SOCK_STREAM, UDP 소켓인 경우 SOCK_DGRAM +- protocol: 0은 시스템이 선택, 6은 TCP, 17은 UDP +
+
+ +# bind() 시스템 콜 +생성한 소켓에 특정 IP주소와 포트 번호를 할당한다. + + bind(sockfd, sockaddr, socklen_t) +- sockfd: 바인딩 할 소켓의 파일 디스크립터 +- sockaddr: 소켓에 바인딩 할 주소 +- socklen_t: sockaddr의 크기 +
+
+ +# listen() 시스템 콜 +클라이언트의 connect 요청을 대기하는 상태가 된다. connection-oriented인 TCP에서만 사용한다. + + listen(sockfd, backlog) +- sockfd: listen을 시작할 소켓의 파일 디스크립터 +- backlog: connection 요청을 대기하는 큐의 크기, 만약 큐가 꽉 차면 운영체제는 큐가 빌 때까지 새로운 connection 요청을 받지 않는다. +
+
+ +# accept() 시스템 콜 +listening을 하다가 새로운 connection이 열리면 accept()는 새로운 소켓을 만들어서 리턴한다. + + accept(sockfd, sockaddr, socklen_t) +- sockfd: connection을 받을, listening 하고 있던 소켓의 파일 디스크립터 +- sockaddr: 클라이언트의 주소 정보 +- socklen_t: 위 주소 정보의 크기 +
+
+ +# 멀티 프로세스 +여러 개의 CPU가 하나 이상의 작업을 동시에 처리(병렬처리)한다. +(*프로세서=CPU코어) + +자식프로세스 생성 - fork() + + pid_t fork() +리턴값이 0이면 자식 프로세스, 0이 아니면 부모 프로세스를 의미한다. + +멀티 프로세스는 각 프로세스가 독립적이기 때문에 한 프로세스가 죽어도 다른 프로세스에는 영향을 주지 않아 안정성이 높다. 하지만 그만큼 많은 메모리 공간과 CPU 시간을 차지한다. +
+
+ +# 병렬 처리 +여러 CPU에서 각 프로세스를 병렬적으로 실행한다. diff --git a/src/practice/chapter1/client.c b/src/practice/chapter1/client.c new file mode 100644 index 0000000..d412ec4 --- /dev/null +++ b/src/practice/chapter1/client.c @@ -0,0 +1,36 @@ +#include +#include +#include + +int main(){ + int client_socket; + struct sockaddr_in clientAddr; + int clientAddr_len, readLen, recvByte, maxBuff; + char message[BUFSIZ]; + char rBuff[BUFSIZ]; + + client_socket = socket(AF_INET, SOCK_STREAM, 0); + + printf("===client===\n"); + + clientAddr.sin_family = AF_INET; // IPv4 주소 체계 + clientAddr.sin_addr.s_addr = INADDR_ANY; // 모든 가능한 IP 주소 + clientAddr.sin_port = htons(9002); + + if(connect(client_socket, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) == -1){ + perror("연결 오류\n"); + return 1; + } + + while(1){ + printf("메시지 입력: "); + fgets(message,BUFSIZ-1,stdin); + + if(strncmp(message, "END", 3) == 0) break; + + send(client_socket, message, BUFSIZ-1, 0); + } + close(client_socket); + + return 0; +} \ No newline at end of file diff --git a/src/practice/chapter1/server.c b/src/practice/chapter1/server.c new file mode 100644 index 0000000..ca82a1a --- /dev/null +++ b/src/practice/chapter1/server.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +int main(){ + int server_socket, client_socket; + int readLen; + char rBuff[BUFSIZ]; + + // 소켓 생성 + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if(server_socket == -1){ + perror("소켓 생성 실패\n"); + return 1; + } + + // + struct sockaddr_in serverAddr, clientAddr; + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; // IPv4 주소 체계 + serverAddr.sin_addr.s_addr = INADDR_ANY; // 모든 가능한 IP 주소 + serverAddr.sin_port = htons(9002); + + // 서버 소켓 바인딩 설정 + if (bind(server_socket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) { + perror("바인딩 실패"); + return 1; + } + + // listen: 클라이언트의 connect 요청을 기다림 + int backlog = 5; // 최대 클라이언트 수 + if(listen(server_socket, backlog) == -1){ + perror("대기 실패"); + return 1; + } + + printf("서버가 클라이언트의 connect 요청을 기다리는 중...\n"); + + socklen_t clientAddr_len = sizeof(client_socket); + client_socket = accept(server_socket, (struct sockaddr *)&clientAddr, &clientAddr_len); + + if(client_socket == -1){ + perror("연결 실패\n"); + return 1; + } + printf("클라이언트 연결 성공\n"); + + while(1){ + readLen = read(client_socket, rBuff, sizeof(rBuff)-1); + rBuff[readLen] = '\0'; + printf("Client: %s", rBuff); + write(client_socket, rBuff, strlen(rBuff)); + } + close(client_socket); + close(server_socket); + + return 0; +} \ No newline at end of file From 7e1edbd1b3e283247aab3afe5931510f00b37fa2 Mon Sep 17 00:00:00 2001 From: qzzloz Date: Wed, 17 Apr 2024 21:14:30 +0900 Subject: [PATCH 2/2] =?UTF-8?q?workbook:=20chapter2=20=EC=9B=8C=ED=81=AC?= =?UTF-8?q?=EB=B6=81=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/chapter2/Ch02Keyword.md | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 docs/chapter2/Ch02Keyword.md diff --git a/docs/chapter2/Ch02Keyword.md b/docs/chapter2/Ch02Keyword.md new file mode 100644 index 0000000..ec1649f --- /dev/null +++ b/docs/chapter2/Ch02Keyword.md @@ -0,0 +1,79 @@ +# Ch02. AWS (VPC & Internet Gateway & EC2) +2주차 워크북 - AWS (VPC & Internet Gateway & EC2) + +
+ +# AWS 리전 +AWS는 수많은 컴퓨팅 서비스를 지원하고 있고, 이를 위한 대규모의 서버용 컴퓨터가 필요할 것이다. 이 때 서버용 컴퓨터를 모두 한 곳에 몰아둔다면 + +1. 서버가 있는 지역에 자연재해가 발생할 경우, 모든 서비스가 마비되고 +2. 자원이 한 곳에 몰려있는 경우, 그곳과 지구 반대편에 위치한 지역은 거리가 멀기 때문에 서비스 속도가 느릴 것이다. + +위와 같은 문제를 해결하기 위해 서비스를 여러 곳에 분산하여 배치하였고, 이를 리전이라고 한다. +- 가용영역 + +리전을 한 번 더 분산시켜 배치한 것이다. 1개 이상의 물리 데이터센터를 묶은 그룹이라고 볼 수 있다. + +- 리전과 가용영역의 차이 + +가용영역은 데이터센터 그룹이고 리전은 가용영역 여러 개로 구성된 **지리적 영역**이다. +
+
+ + +# 라우팅 +- source -> dest까지 패킷의 이동경로를 설정하는 것 + +
+
+ +# VPC +VPC(Virtual Private Cloud): AWS에서 제공하는 가상 네트워킹 환경, 사설 IP주소를 가진다. + +
+
+ +# VPC 실제 사용 +VPC는 실제 사용 될 때, VPC 자체에서도 서브넷을 나눠서 원하는 가용영역에 배치하여 사용한다. 이 때, + +1. 첫 주소 : 서브넷의 네트워크 대역 +2. 두번째 : VPC 라우터에 할당 +3. 세번째 : Amazon이 제공하는 DNS에 할당 +4. 미래를 위해 예약 +5. 브로드 캐스트 주소 + +로 사용되기 때문에 이들은 호스트 주소로 할당할 수 없다. (예약되어 있다.) + +1. 첫 번째 주소 + +만약 서브넷의 CIDR 블록이 10.0.0.0/24라면, 여기서 10.0.0.0은 네트워크 주소이다. + +2. 두 번째 + +VPC 라우터에 할당되는 주소이다. 만약 CIDR 블록이 10.0.0.0/16이고 서브넷의 CIDR 블록이 10.0.1.0/24라면 두 번째 주소는 10.0.1.1이 된다. + +3. 세 번째 + +이 주소는 인스턴스가 도메인 이름을 해석할 때 사용된다. + +
+
+ +# 포트포워딩 +포트포워딩은 패킷이 라우터나 게이트웨이를 통과하는 동안 이 패킷이 어느 포트로 가야할 지 결정해주는 것을 말한다. + +예를 들어, + +공유기를 설치하고 공유기와 연결된 여러 PC가 있다고 하자. PC들은 공유기로부터 IP를 부여받는다. 외부에서 들어오는 패킷은 많은 PC 중 어느 PC로 가야하는지 길을 찾지 못할 것이다. (이 때는 공유기의 포트 번호르 들고 오기 때문에) + +그래서 패킷이 올바른 PC를 찾아갈 수 있도록 공유기는 NAT table을 참고하여 해당 PC의 포트번호를 패킷에게 알려준다. + +
+
+ +# NAT 프로토콜 +게이트웨이에서 외부 네트워크로 나갈 때는 네트워크 내부의 사설IP가 아닌 공인IP주소로 바뀐다. +
+
+ +# Private Subnet \ No newline at end of file