일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- DFS
- 다익스트라 알고리즘(Dijkstra Algorithm)
- 이분 탐색(Binary Search)
- 위상 정렬(Topological Sort)
- 백준 17608번
- 트리(Tree)
- 백준 21606번
- 스택(Stack)
- 백준 1707번
- DFS(Depth First Search)
- 백준 1948번
- 동적 프로그래밍(Dynamic Programming)
- 이분 그래프(Bipartite Graph)
- 그리디 알고리즘(Greedy Algorithm)
- 위상 정렬(Topology Sort)
- 백준 2261번
- 백준 2493번
- BFS
- 백준 18352번
- 백준 9012번
- 백준 2504번
- BFS(Breadth First Search)
- 그래프(Graph)
- 알고리즘 개념
- 백준 2812번
- 분할 정복(Divide and Conquer)
- 플로이드 워셜 알고리즘(Floyd-Warshall Algorithm)
- 큐(Queue)
- 백준 10000번
- DFS & BFS
- Today
- Total
Always Be Wise
소켓과 소켓 인터페이스 본문
소켓은 네트워크 연결의 종단점을 의미한다. 네트워크 상에서 서버와 클라이언트 두 개의 프로그램이 특정 포트를 통해 양방향
통신이 가능하도록 만들어주는 소프트웨어 장치라고 할 수 있다. 따라서 통신할 두 프로그램 모두에 소켓이 생성되어야 한다.
위의 그림은 소켓 인터페이스 기반 네트워크 응용 프로그램의 개요를 보여준다. 소켓 주소는 sockaddr_in 타입의 16바이트
구조체에 저장된다. 구조체 안의 sin_family는 항상 AF_INET으로 32비트 IP 주소를 사용하고 있다는 것을 의미하며, sin_port는
16비트 포트 번호, sin_addr는 32비트 IP 주소를 의미한다. IP 주소와 포트 번호는 항상 네트워크 바이트 순서(Big Endian 방식)로
저장된다. siz_zero의 경우, 16 바이트 크기(아래 정의한 sockaddr 구조체의 크기)를 맞추기 위한 패딩이다. sockaddr 구조체는
포괄적인 소켓 주소 구조체로 어떤 종류의 소켓 주소 구조체라도 캐스팅하여 사용하기 위해 정의한다.
socket 함수
클라이언트와 서버는 소켓 식별자를 생성하기 위해 socket 함수를 사용한다. 아래는 클라이언트 입장에서 식별자를 생성한 것이다.
여기서 AF_INET은 32비트 IP 주소 사용을 의미하며, SOCK_STREAM은 소켓이 인터넷 연결의 종단점으로 TCP 프로토콜을
따른다는 것을 나타낸다. type에서 프로토콜이 결정될 경우, 세 번째 protocl 인자는 0으로 입력한다. socket에 의해 리턴된
clientfd 식별자는 부분적으로 열린 것이며, 아직은 읽거나 쓸 수 없다. 소켓의 오픈 과정은 클라이언트인지 서버인지에 따라 다르다.
Client : connect 함수
클라이언트는 connect 함수를 호출해서 addr에 있는 서버의 소켓 주소와 연결을 시도한다. 연결이 성공적으로 이루어진다면
clientfd 식별자는 이제 읽거나 쓸 준비가 된다. 해당 연결은 다음과 같은 소켓 쌍으로 규정된다. 이때 x는 클라이언트의 IP 주소이고,
y는 클라이언트 프로세스를 유일하게 식별하는 단기 포트를 의미한다.
Server : bind 함수
서버는 bind 함수를 통해 addr에 있는 서버의 소켓 주소를 소켓 식별자 sockfd와 연결한다.
Server : listen 함수
클라이언트는 연결 요청을 개시하는 능동적 개체이다. 반면, 서버는 클라이언트로부터 연결 요청을 기다리는 수동적 개체이다.
기본적으로 커널은 socket 함수가 만든 식별자를 클라이언트 입장에서 생성된 것으로 간주한다. 이에 listen 함수를 호출하여
해당 식별자를 클라이언트가 아닌 서버에서 사용할 것임을 알려주어야 한다. 즉, listen 함수는 sockfd를 듣기 소켓으로 변환하며,
듣기 소켓은 클라이언트로부터의 연결 요청을 승낙(accept)할 수 있다.
Server : accept 함수
서버는 클라이언트로부터 연결 요청을 기다리며, 요청이 도착하면 addr에 있는 클라이언트의 소켓 주소를 채우고 클라이언트와의
통신을 위해 사용될 연결 식별자(connected descriptor)를 반환한다.
getaddrinfo 함수
getaddrinfo 함수를 사용하면 특정 IP 프로토콜 버전에 의존하지 않는 네트워크 프로그램을 작성할 수 있다. getaddrinfo 함수는
인자로 host와 service가 주어지면 addrinfo 구조체로 이루어진 연결 리스트 result를 리턴한다. 이때, addrinfo 구조체는
각 host와 service에 대응되는 소켓 주소 구조체를 가리키고 있다. getaddrinfo의 host 인자는 숫자 IP 주소 혹은 도메인 이름이다.
service 인자는 http와 같은 서비스 이름 혹은 십진수 포트 번호이다. hints 인자는 선택적으로 사용할 수 있는 인자이며, 함수가
리턴하는 연결 리스트 전반에 영향을 준다. 클라이언트에서 getaddrinfo를 호출할 경우, socket 및 connect 함수 호출이 성공하여
연결이 성립될 때까지 연결 리스트를 돌며 addrinfo에 담겨 있는 각각의 소켓 주소들을 시도한다. 서버에서 호출할 경우, socket 및
bind 함수 호출이 성공하고, 식별자가 유효한 소켓 주소에 연결될 때까지 연결 리스트 상의 소켓 주소들을 시도한다.
getnameinfo 함수
getnameinfo 함수는 getaddrinfo의 역이다. 소켓 주소 구조체를대응되는 호스트와 서비스 이름 스트링으로 변환한다.
open_clientfd 함수
클라이언트는 open_clientfd 함수를 호출하여 서버와 연결을 설정한다. 인자로 hostname(서버의 IP 주소(이름))과
port(포트 번호)를 입력받는다. 아래는 open_clientfd 함수의 코드이다. 함수 내부에서 getaddrinfo 함수를 호출하여 addr_info
구조체로 이루어진 연결 리스트를 리턴 받는다. 해당 리스트는 입력받은 hostname과 port와 연결하기에 적합한 소켓 주소 구조체를
가리키고 있다. 이후, 이 리스트를 돌면서 socket과 connect 함수 호출을 시도한다.
open_listenfd 함수
서버는 open_listenfd 함수를 호출하여 연결 요청을 받을 준비가 된 듣기 식별자(listenfd)를 생성한다. 호출시 함수의 인자로
port(서버의 포트 번호)를 입력 받는다. 아래는 open_listenfd 함수의 코드이다. 함수 내부에서 getaddrinfo 함수를 호출하여
addr_info 구조체로 이루어진 연결 리스트를 리턴 받는다. 해당 리스트는 입력받은 hostname과 port와 연결하기에 적합한 소켓
주소 구조체를 가리키고 있다. 이후, 이 리스트를 돌면서 socket과 bind 함수 호출을 시도한다.
'컴퓨터 시스템 > CSAPP' 카테고리의 다른 글
웹 서버 (0) | 2021.12.20 |
---|---|
시스템 수준 입출력 (0) | 2021.12.20 |
글로벌 IP 인터넷 (0) | 2021.12.16 |
네트워크 프로그래밍 (0) | 2021.12.16 |
동적 메모리 할당 - malloc 함수 구현(분리 가용 리스트) (0) | 2021.12.15 |