Computer Science/Network

네트워크 응용설계 과제 3

mayleaf 2022. 5. 3. 01:58

과제 내용이 다중 클라이언트를 받을 수 있는 TCP 서버를 go로 띄우는 과제였다.

Extra과제는 c로 짜는 것이었고, 둘다 짜서 제출했다.

과제 요구사항

1. 요청에 대한 응답을 잘 내려주기

2. 에러 핸들링 잘하기

3. 1분 마다 커넥션 수 찍어주기였다.

Go 로 풀기

1.풀이

기본적으로 tcp connection 요청을 accept하는 것을 메인 루틴에서 실행하고

이후 커넥션이 맺어진 후의 처리는 go routine으로 넘기는 식으로 처리했다.

2. 에러 처리

에러는 err != nil 로 떡칠해서 풀었다.

3. 1분마다 커넥션 수 찍기

이 경우 go로 짤때는 go routine으로 서버가 현재 돌아가고 있는 시간을 확인하는 식으로 처리했다.

 

Extra과제의 경우 (c로 짜기)

다중 클라이언트를 받을 수 있는 TCP서버와 함께 TCP 클라이언트도 다시 짜야했다.

그리고 다중 클라이언트 처리를 select 로 짜는게 조건이었다.

 

고는 전에 TCP 부하테스트 프로그램 짜는 것 때문에 해봤어서 그냥 그랬다.

Extra 과제에서는 c로 소켓통신을 하는 것은 처음이어서 재미있었다.

 

1. 풀이

먼저 소켓 개수의 상한을 두고, 마스터 소켓을 만든다.

마스터 소켓을 포트에 바인딩해준다음에 select를 이용해서 파일 디스크립터에 변화가 있으면 처리를 해주는 식으로 접근했다.

마스터 소켓 파일에 변화가 있으면 커넥션 요청이므로 새로 소켓 만들고 파일디스크립터 셋에 추가해주도록 처리해주고

inetntoa 함수로 ip주소도 출력해주고 이것저것 과제에서 요구하는 것들을 처리했다.

 

다른 파일 디스크립터의 경우 변화가 있으면 요청이 들어온거거나 아니면 커넥션이 끊긴건데

일단 파일 디스크립터를 읽어보고 읽어온 버퍼의 길이가 0이면 커넥션이 끊긴걸로 판단하는 식으로 disconnecting처리해줬다.

 

2. 에러 처리

죄다 길이 확인하는 식으로 길이가 이상한 부분에 대해서 에러 처리했다.

ctrl-c 인터럽트는 signal 함수 써서 풀었다.

 

3. 1분마다 커넥션 수 찍기

3번은 pthread로 time만 확인해주는 쓰레드를 하나 만들어서 문제를 해결했다.

 

이번 과제에서는 이 부분이 고민이 많았다.

당시에 생각난 방식은 두 가지가 있었는데 1. 이걸 쓰레드를 하나 더 만들어서 짤까, 2. 파일디스크립터 셋에 넣고 select로 풀어버릴까 이렇게 두가지였다.

 

그런데 그런데 1번으로 해결한 것은 아래와 같은 이유 때문이었다.

나는 통신 부분부터 구현했고, 타이머로 소켓을 찍는걸 가장 마지막에 구현했다. 통신을 처리하는 코드는 하나의 select에서 파일디스크립터 셋의 변화를 감지하도록 구현했다. 변화가 감지되고나면 for 루프 내부에서 파일 디스크립터 셋을 모두 확인하도록 구현했는데 코드를 덜 짜려면 타이머도 이 for 루프 안에서 처리해야 했다. 이때, 내부에서 소켓과 무관한 분기가 하나 추가되는게 보기 좋지 않았다고 느꼈고, 타이머 때문에 파일에 계속 변화가 일어나고 select가 호출되는것도 별로라고 느꼈다.

마지막으로 기능의 정확성도 의구심이 들었다. select가 파일 변화를 감지하고 소켓의 for loop를 쭉 돌고 난 다음에야 타이머를 찍으면 타이머가 정말 제 시간에 측정이 될까? 하는 생각이었다. 이런 생각때문에 타이머는 멀티쓰레드로 풀었다.

 

지금 생각해보면 파일 변화 감지후 커넥션 수를 제일 먼저 출력해주면 이것도옳은 풀이였을 것이다. 문제를 풀고 있을 때는 타이머를 돌리는 시간이 소켓들을 확인한 다음을 기준으로 생각했는데 타이머 먼저 찍었으면 1번이나, 2번이나 같은 풀이였을 것이다.

후기

예전에는 c 너무 저수준이라서 쓰기 어렵다라는 생각뿐이었는데 운영체제와 이것저것 다른 공부를 하다보니까

c에서 파일 디스크립터 셋을 직접 다루거나 select써보는게 처음임에도 불구하고 재미있게 풀었다.

 

그러고보니 c 과제를 하면서 여기까지 해줘야했구나? 하는 부분이 있었다.

c 클라이언트에서 커넥션 요청하는 부분이었는데

hostname으로 커넥션 요청하면 안되고, hostname 기반으로 ip주소 얻어와서 ipv4양식으로 요청을 했어야했다.

이때 딱 "역시 C언어다" 하는 순간이 있었다.

 

c언어 생각보다 고수준 언어일지도 모르겠다.

'Computer Science > Network' 카테고리의 다른 글

What I cannot learn on the network class - 1. SMTP  (0) 2022.04.26