관리 메뉴

막내의 막무가내 프로그래밍 & 일상

[네트워크] HTTP Sever using TCP Socket (feat. docker, cURL, wireshark) 본문

네트워크/도커(Docker)

[네트워크] HTTP Sever using TCP Socket (feat. docker, cURL, wireshark)

막무가내막내 2019. 12. 18. 02:17
728x90

도커를 서버로 두고 다른 컴퓨터를 클라이언트로 두어 소켓 통신을 사용해 웹페이지 서빙을 해보았다.

 

[선 결론]

TCP 소켓을 사용해서 HTTP 서버를 만들었다. 클라이언트와 서버 소캣 파이썬 코드를 각각 만들어 통신을 해보고, cURL, Telnet, Web browser를 통해서도 소켓 서버에 요청과 응답을 받아봤다. 또한 브라우저로 접속했을때 내가 만든 웹사이트를 띄워주도록 하였다. 마지막으로 wireshark를 통해서 packet capture를 하여 tcp소켓 통신을 어떻게 하는지 볼 수 있었다.

 

 

 

먼저 서버가될 docker 컨테이너 서버 소캣의 ip를 설정해주기 위해 docker 컨테이너내에서 ifconfig로 확인한 결과이다

docker ifconfig

도커 로컬 ip가 172.17.0.2임을 알 수 있다.

 

 

그래서 http_tcp.py(서버 소캣) IP를 다음과 같이 설정하였다. (부분 캡처)

 

 

 

 

 

 

 

와이파이를 통해서 윈도우 컴퓨터나 외부에서 도커 컨 테이너의 소켓 서버에 접속할 것이므로 클라이언트에 ifconfig 명령어를 통해 ens33 IP를 확인했다.(Bridge) 192.168.0.164임 을 알 수 있다.  (뒤에 코드에서 다른 장소에서 한것도 있으므로 ip가 달라진게 있다.)

 

 

 

 

 

 

다음은 소캣 서버 코드인 http_tcp.py이다. (미리 파일을 첨부한다.)

1. setting.py
0.07MB
client2.py
0.00MB
http_tcp.py
0.00MB
http_tcp.py

기본 ip와 port는 앞서 확인한 도커 컨테이너 ip로 설정하였 다. 그리고 포트는 도커 컨테이너를 만들 때 1234:80 으로 포트포워딩 하였으므로 80으로 설정하였다.  open_server_socket 서버를 연 후 클라이언트의 접속에 대기한다. 

 

그리고 클라이언트의 접속 요청이 오면 http를 읽어들여 파일 경로를 파싱해준 후 해당 경로의 파일을 open()읽어 들인다. 추가로 String형태로 outputdata에 저장한다. 저는 /index.html만 준비해놨고 다른 경로가 오면 예외처리로 404 코드와 함께 noIndex.html을 불러오게 했다. 조교님의 실행영상에서 출력문이 나왔던 것도 똑같이 출력되게 해주었다. conn.getpeername()으로 연결된 상대(클라이언트) 의 address(주소)를 얻었다.  getsocketname() 으로는  포트 번호를 출력시켜주었다. 클라이언트에게 응답을 보내주는 것은 send() 메소드를 통해서 보내주었다. 내용은 HTTP 형식에 맞게 보내주고 요청한 데이 터를 보내주었다. 응답을 보내줄 때는 utf-8로 인코딩해주어 보내줘야한다. 응답 데이터를 클라이언트에게 모두 보내준 후 연결은 close로 끊는다.

 

요청과 응답의 형식은 다음과 같다.

요청: [HTTP Method] [파일경로] [프로토콜]

응답: HTTP/1.1 200 OK

 


 

'Web browser로 서버에 요청 및 통신한 결과이다.

(클라이언트는 노트북 윈도우, 서버는 노트북 vmware docker container이다)

웹페이지가 잘 서빙됨을 알 수 있다. 또한 서버쪽에 클라이언 트 메시지를 print문으로 출력해주었는데 192.168.0.208 IP이 고 51393 포트를 통해 옴을 알 수 있었다.

 

 

 

Wireshark의 결과이다. 요청과 응답이 잘 왔음을 볼 수 있다. HTTP 부분을 보면 클라이언트에서 서버로 요청시 GET /index.html HTTP/1.1로 통신했음을 볼 수 있다. 또한 서버 에서 클라이언트로 요청할 때는 요청에 에러사항이 없으므로 200 OK 응답코드와 index.html의 데이터를 보내줌을 볼 수 있다. 

 

 

 

 

 

 

 

 

 

다음은 404 에러페이지이다. /index.html로 요청을 보내지 않 은 경우 모두 noIndex.html과 404 Not Found 응답을 보내 게 해놓았다. 
패킷 패킷 캡처 결과를 보면 내가 정하지 않는 경로 / 로 요청을 보내어 404 Not Found를 응답으로 보냈음을 볼 수 있다. 원래의 웹페이지라면 /로 요청했을 시 기본페이지(ex index.html)을 서빙해주는게 맞지만 본 과제는 소켓 통신이 목 적이므로 이렇게 구현을 했다. 추가로 소켓 서버를 80으로 열 어놨으므로 외부에서는 포트포워딩된 1234 TCP 포트로 접속함을 볼 수 있었다. 그리고 cURL, telnet도 결과는 거의 똑같이 나올거라 고 예측할 수 있다.
 

 

 


 

 

 

cURL 명령어 결과입니다.

요청과 응답이 잘 됨을 볼 수 있다.

밑은 cURL의 패킷캡처 결과이다.

 

 


 

 

 

 

 telnet 명령어의 결과이다.

(서버)

 

 

(클라이언트) => 친구의 맥북

밑은 와이어샤크 결과이다.

 

 

 

 

 


 

 

클라이언트 소켓과 서버 소켓의 결과이다

(클라이언트 서버 소켓 코드.py)

클라이언트 

클라이언트 소캣은 지정된 ip와 TCP 포트로 연결을 시도한다. 
그 후 위와 같이 요청을 보내준다. 난 GET 요청과 /index.html을 파일경로로 하여 보냈다. 그 후 응답이 오면 응답받은 데이터를 print문으로 출력해주고 연결을 끊게 했다.

 

 

 

통신이 잘됨을 볼 수 있다.

 

 

다음은 와아어샤크 패킷캡쳐 결과이다.

 

 

 

 

 


 

마지막으로 도커 내의 django 웹 어플리케이션과의 패킷캡쳐 결과이다. 

(서버는 vmware에서의 도커, 클라이언트는 윈도우 노트북)

 

 

 

 

 


총정리하면, 모두 실행하는 방식만 다를 뿐

 

 

위와 같은 구조로 http server, tcp 소캣 통신이 이루어짐을 직접 구현을 통해 알 수 있었다. TCP server가 소켓을 열어놓고 클라이언트 의 요청을 받을 준비를 하고 클라이언트가 소켓 서버에 연결을 하고 요청을 하면 소켓 서버는 요청을 받고 요청에 맞게 응답 을 해주고 연결이 서로 끊어지게 된다.

 

 

 

댓글과 공감은 큰 힘이됩니다. 감사합니다.!

728x90
Comments