네트웍 프로그램시 주의할 사항 (buggy 코드를 없애자!!)

1. 기반 프레임웍 개발시 유의할 점
+-----+
|  A  |
+-----+
|  B  |
+-----+
|  C  |
+-----+

C라고 하는 모듈(또는 클래스)를 B라는 모듈로 Wrapping하고, B라는 모듈을 A모듈로 Wrapping하는 아키텍쳐가 있다고 가정하자.

이 때 유의사항은 A가 C의 기능을 사용하지 않아도 될 정도로 B의 API가 General해야 한다.

하지만, B의 API가 General하게 디자인이 되지 않았을 경우 (일명 찜찜하게 설계된 경우 문제가 생길 소지가 있다.)
예를 들자면, C는 Telnet통신을 위한 모듈이다. Telnet은 read,write가 sync가 되지 않기 까닭에 쓰레드를 이용하여 write와 read를 따로 쓰이도록 한다.

이때 B는 이런 Telnet 통신에 대한 연결과 read, write에 대해서 general하게 디자인을 해놨다. A는 C를 생각하지 않아도 B의 API만을 가지고, Telnet 통신을 할 수 있도록 디자인이 되는 걸 전제로 B의 API를 이용하여 코딩을 하게 된다
문제는 바로 B의 API의 기능이 잘못될 경우이다.

먼저 예로 들었던 Telnet인 경우에 B모듈에 close(), connect(), connect(String ip, int port) 라는 Telnet 통신 프로토콜이 있다고 가정하자.
이때, close()는 read,write에 대한 thread를 종료하는 것이며, 두 connect는 read, write에 대한 thread를 생성하고 read,write를 받아들일 수 있도록 준비가 되는 코드가 만들어져야 한다.

즉, B의 일부 API인 connect()와 connect(String ip, int port)는 기본적인 기능은 같아야 불구하고도 같지않을때, buggy한 코드를 생성할 수 있다.



2. 노드간 통신

네트웍 프로그램에서 가장 중요한 것은 노드와 노드간의 연결성이다.

때에 따라서 항상 지속적으로 연결이 보장되어야 하는 경우도 있을 수 있고, 필요할 때마가 연결을 하는 경우가 있다.
필요할 때마다 연결을 하는 경우는 보통 문제가 명확한 반면, 항상 연결이 보장되어야 하는 경우의 통신 프로그래밍을 하는 경우는 상당히(개인적인 체험에서 나온 말이다.) 힘들 수도 있다.

low-level 통신인 경우에는 sync코드 와 crc외 각종 FEC등을 사용하여 Qos를 보장해야 하는 반면, high-level인 경우는 Qos를 보장한다고 가정하고, 여러 상황에 대한 대비책(?)을 강구해야 한다.

예를 들어, 계속 연결을 보장해야 하는 통신 노드간의 에러 상황에 대해서 처리하는 방법은 다음이 좋을 수도 있다.
더 좋은 방법이 있는지는 모르겠다.
          <--------
   A                      B
(client)    -------->    (server)


A노드의 클라이언트 프로세스가 B노드의 서버 프로세스가 제대로 동작되는지 확인하는 api를 잘 생각해 보자.

1. A노드에 B의 API인 ping 명령를 요청하여 B가 현재 제대로 동작 중인지를 확인한다.
  좀 더 확실하기 위해서 ping 명령어를 통해서 네트웍의 상황을 체크할 수도 있다.

2. 만약 B의 운영체제가 문제가 있어서 응답을 못할 수도 있고, B노드에서 동작중인 프로세스가 종료되는 경우가 있다.
  이 경우는 1번에서 요청한 ping명령에 대해서 무응답이 되기 까닭에 A와 B의 연결이 끊어졌으면 내버려 두고, A와 B의 연결이 되어 있는 경우는 socket 연결을 끊고, 다시 연결하도록 한다.

3. A노드는 B노드와 통신에 대한 effect를 고려해 플래그를 설정하여 A노드를 통해서 B노드에 요청해야 하는 상황에 대비하여 불필요한 경우에 대해서 접속을 시도 하지 않음으로서, 처리 속도를 높이고 리소스를 낭비하는 일이 없도록 한다.

4. 2번 마지막에서 A노드에서 B노드로 다시 연결을 요청하고 성공할 경우에 대해서 1번에서처럼 A노드의 클라이언트 프로세스가 B노드의 서버프로세스가 동작이 제대로 될 수 있는지 확인하는 ping 요청을 하도록 한다



3. 기반 운영체제

항상 endian를 조심하자. 운영체제마다 big-endian, middle-endian, little-endian을 사용한다.
Posted by 김용환 '김용환'