-
[SW 정글 53일차] 소켓을 구현하긴 했는데 나는 소켓을 완벽히 이해했을까기타/SW 사관학교 정글 2021. 9. 25. 02:26
이번 주차는 웹 서버를 만드는 주차로 소켓 인터페이스를 활용하여 Tiny 서버를 구현하고 로컬로 클라이언트(웹 브라우저)에서 요청을 보내어 응답을 받는 것을 확인했다.
너무 신기했고 대학교 때 전공으로 배웠던 것을 소프트웨어적으로 만들어보았다는 것에 성취감도 느껴졌다.
그 후에, 프록시를 공부하고 구현해보려고 했는데 문득 '내가 소켓을 잘 알고 사용한 것일까?', '소켓은 왜 나왔을까?, '소켓은 반드시 필요할까?'라는 의문이 들었다.
그래서 프록시를 구현하는 시간을 가지기 전에 소켓에 대해 더 알아보려고 한다.
소켓은 무엇일까?
소켓은 two-way commuication channel에서 endpoint라고 말할 수 있는데 다양한 구조체 정의를 봤겠지만 기본적으로는 IP주소와 포트번호 정보를 가지고 있다.
이러한 소켓을 사용하여 이루어진 communication channel으로 local 혹은 network 환경에 있는 application program들 사이에서 데이터를 주고 받을 수 있는 것이다.
소켓은 단지 process간의 통신 channel을 개통하기 위한 인터페이스라고 생각하면 되고 그냥 파일의 한 종류라고 생각하여 open, read, write, close와 같은 system call이 이루어진다고 보면 된다.
조금 더 자세히 말하면 소켓을 사용하여 서로 다른 컴퓨터들끼리 통신하는 것은 표준 UNIX file descriptor를 사용하는 것이다.
UNIX에서의 모든 I/O(Inut & Output) 동작은 file descriptor를 writing하고 reading하는 것이라고 볼 수 있다.
여기서 말하는 file descriptor에 대해 짧게 설명하면 open file과 연관된 비음수형 정수인데 이 file descriptor가 네트워크 연결이 될 수 있고 텍스트 파일, 터미널 등등이 될 수 있는 것이다.
더 자세히 알고 싶으면 이전에 내가 정리한 블로그를 참고하면 좋을 것 같다.
https://straw961030.tistory.com/238
이러한 소켓은 BSD를 통해 처음 개념이 나왔는데 BSD에서 설계한 socket API가 내가 컴퓨터 시스템 책에서 보고 배웠던 소켓 인터페이스와 그에 맞는 socket(), connect(), bind() 등 함수들을 정의한 것이다.
그리고 컴퓨터 시스템에 나와있는 것은 socket type이 stream이고 그 외의 type인 datagram과 raw에 대해서도 알 필요가 있다.
stream과 datagram type의 차이점은 이전 블로그에 정리한 적이 있다.
stream type은 아래 블로그 글에 정리한 적이 있어서 여기서는 datagram type에 대해서만 정리하려고 한다.
https://straw961030.tistory.com/235
datagram type의 소켓 인터페이스는 아래와 같다.
stream type에서의 인터페이스와 비교했을 때 큰 차이점은 클라이언트에 connect(), 서버에 listen(), accept()가 없는 것이다.
클라이언트와 서버가 connection과정없이 어떻게 통신이 이루어질 수 있지?라는 의문이 들었다.
내 개인적인 생각은 datagram type이 UDP를 사용하여 통신하는 것이고 UDP의 특징 중 하나는 비연결성이기에 그 특징을 묘사한 것이라고 생각한다.
서버 측을 먼저 보면 bind()까지는 stream type과 똑같고 그 뒤에 이어지는 recvfrom()은 데이터가 도착하기를 제한시간 없이 기다리면서 데이터를 수신하는 역할을 한다.
recvfrom(s, buf, buflen, flags, (struct sockaddr *) &from, &fromlen);
recvfrom()의 형태이다.
여기서, fromlen인자 값으로 주어진 것을 통해 from buffer의 크기를 지정한다.
그리고, 실제 from(받은 데이터그램)이 버퍼에 들어온만큼의 크기를 return 시에 fromlen의 값에 업데이트 시켜준다.
다음으로 sendto()를 통해 요청에 대한 응답을 클라이언트에게 보내준다.
sendto(s, buf, buflen, flags, (struct sockaddr *) &to, tolen);
s, buf, buflen, flags는 stream socket 인터페이스에서 본 것이다.
그러면 여기서 새롭게 주어진 to, tolen은 클라이언트의 소켓 주소와 길이를 가리킨다.
여기까지는 주어진 인터페이스 디자인에 대한 해석이다.
그러면 위에서 던진 connect()단계가 왜 없을까라는 의문은 어떻게 풀까?
https://docs.oracle.com/cd/E37838_01/html/E61059/sockets-14.html
위 페이지의 말을 인용하면 Datagram socket도 특정한 도착지 주소를 연관시키기위해 connect() system call을 사용할 수 있다는 것이다.
솔직히 이 부분은 아직 이해가 안간다.
그러면 stream socket 방식가 차이점이 없이지는게 아닐까하는 의문도 들고 아직 UDP에 대한 지식도 충분하지 않은 것도 있다.
일단은 여기까지 다시 알아보면서 소켓에 대한 개념이 더 잡혔다는 느낌이 든다.
[오늘의 나는 어땠을까?]
'기타 > SW 사관학교 정글' 카테고리의 다른 글
[SW 정글 55일차] HEAD 메소드는 왜 쓸까? (0) 2021.09.26 [SW 정글 54일차] IP 5계층 (0) 2021.09.26 [SW 정글 52일차] 오늘은 일기만.. (0) 2021.09.24 [SW 정글 52일차] Proxy (0) 2021.09.22 [SW 정글 51일차] MIME 타입, CGI, datagram vs stream (0) 2021.09.22