본문 바로가기

프로그래밍 실력쌓기

네트웍 통신에서 알아야 할것



네트웍 통신에서 알아야 할것


먼저 알려드리고 싶은것은 이글은 강좌가 아니며 이전글과 마찬가지로 제가 그냥 머리속에 떠오르는대로 적을건데요.

네트웍 통신 분야의 키워드들의 나열 그리고 개인적인 의견 짧막한 지식이 주요 내용이 될거 같습니다.


TCP와 UDP


1. TCP와 UDP의 차이점을 알아야 합니다. 찾아보면 많이 나올거에요.


2. TCP


연결을 먼저 해야합니다. 내가 연결하려는 원격지가 공인IP여야 가능합니다. UDP는 Private IP여도 가능한 방법이 있습니다. 그건 아래 더 내려가면 나옵니다.


예전에 모뎀을 쓸때는 ARJ 파일을 받으면 데이타가 맞지 않아 압축이 풀리지 않는 경우가 많았습니다. 하지만 TCP를 쓰면 그런일이 없습니다. 받았다면 제대로된 데이타 입니다. 


하지만 모든게 다 이론대로 되지 않죠? 그래서 정말 중요한 데이타를 받아야 할때는 추가 장치를 마련합니다. MD5 해쉬값입니다. 파일을 MD5로 돌린 값을 파일과 함께 배포해서 유저가 받은 파일이 정말 제대로된 파일인지 확인할수 있게 해줍니다.




http://sourceforge.net/projects/net-snmp/files/net-snmp/5.7.2.1/


TCP는 먼저보낸게 먼저 도착하고 뭐 이런 저런 것들이 있는데.. 이건 검색하면 많이 나오니깐 패스~


TCP로 패킷을 1메가짜리를 보내면 실제로 상대방에서 1메가가 통채로 가는게 아니라 나눠서 보냅니다. 그래서 받는 쪽은 1메가를 다 받고 처리해야 되니깐 1메가를 다 받을때까지 버퍼링을 해야 되요. 이와 관련 하여 MTU라는 값이 있습니다. 이것도 찾아보면 많음


TCP로는 중요한 패킷을 보낸다고 생각하면 됩니다.


그런데 TCP가 보내는 패킷들이 신뢰가 보장되고 순서가 보장되고 그런특징들이 있는데 네트웍 상황들이 워낙 많아서 여러가지 테스트를 하는게 중요합니다. (랜선도 뽑아보고 네트웍 어댑터도 꺼보고 Timeout도 발생시켜보고)




3. UDP


UDP는 순서가 보장이 안됩니다. 원격지에 패킷이 보낸 순서대로 도착하지 않기 때문에 순서를 꼭지켜야 하는 곳엔 쓸수 없습니다. 패킷간에 의존도가 없어야 한다는 말이죠. 아니면 순서가 달라도 크리티컬 하지 않던가.


그리고 이건 받았는지 확인안하기 때문에 도착했는지 알수 없습니다. 그래서 빠르죠.

TCP는 상대방이 응답을 하지 않으면 먹통이 됩니다.


동영상 전송, P2P 전송등에 쓰입니다. 여기서 집고 넣어가야 할것이 봐라 UDP Hole Punching인데 공유기 같은것에 컴퓨터를 물리면 사설IP니깐 다른사람이 내 컴퓨터에 연결 할수 없겠죠. 이때 쓰는건데 검색 ㄱㄱ


하지만 Hole Punching은 100% 신뢰 할수는 없습니다. (안된다는 상황도 가정하고 설계하시는게 좋을듯)


UDP를 쓰면 아예 안갈수도 있어요 유실율이라고 하는데 로컬에서도 있다는데 진짜 그런지는 잘 모르겠네요.




4. HTTP


TCP로 소켓연결을 하면 겁나 짜증나는게 연결이 끊기면 다시 재접속을 해줘야 되요. 그런데 메신져 같은것은 그냥 간단히 재접속하면 되는데 클라이언트 로딩시간이 긴 게임의 경우엔 유저들을 짜쯩나게 합니다. 그냥 연결만 복구할수도 있겠지만 그럼 발생하는 예외들을 다 처리 해야 되니깐 그냥 게임 꺼버리고 다시 로그인하게 하죠..


그래서 가능하면 게임을 HTTP로 만들면 좋습니다. 패킷을 보내면 연결을 했다 끊거든요. 그래서 서비스중에 패치도 가능합니다. ^^ 잠깐의 장애가 있겠지만...


안정적인 각종 웹언어와 프레임웍들이 많아서 두발 뻗고 잘수 있습니다.




5. Serializing, Deserializing


속도가 중요한 게임게발에선 그냥 구조체를 메모리 직렬화 하는데 조금 여유가 있다면 객체를  Json으로 통신합니다. xml 로도 하구요. 메모리를 그냥 직렬화 해버리면 패킷을 캡쳐해서 보면 이진 데이들이 있으니깐 디버깅하기 힘듭니다.

Text기반이면 디버깅할때 너무 편해요.




6. IOCP


OS가 윈도우라면 OS차원에서 지원하는 IOCP라는게 있습니다. 제일 빠르답니다. 아마 지금도 그럴듯..




7. 프로토콜 설계


한번쯤 해보시면 좋을듯.





8. 라이브러리


LibEvent, Thrift.. 좋은게 있으면 쓰면 좋겠죠. 문서화도 잘 되있고 버그도 없고~

네트웍코어 개발하던 개발자는 퇴사하고 버그는 잡기 너무 어렵고 문서화도 안되있고

인수인계가 제대로 되있을리 만무하고 가급적이면 사서 쓸수 있으면 사서 쓰는것도 좋다도 생각합니다.




9. 문제해결


통신쪽은 문제가 생기면 문제점을 찾는게 굉장히 어렵습니다. 같은 상황을 재현하기가 힘들고 뭐 딱히 문제를 해결하는 정도라는게 없습니다. 


패킷도 캡쳐해서 보고

(HTTP의 경우엔 Fiddler 다른통신을 할땐 WireShark나 Microsoft Network Monitor를 씁니다.)


Window의 경우 netstat -na Linux의 경우 netstat -tnlp를 써서 어떤 포트가 열려있는지 확인도 하고


서버에 접속되는지 확인할땐 Ping은 거의다 막아놓으니깐 

Telnet (ip) (port)으로 간단하게 연결 확인도 해봅니다.


코드를 확인하는건 당연한거고...





10. 서버구조


서버는 포트를 열고 클라이언트에서 연결해주길 기다리고 있습니다.


서버가 해야 되는일은 

Network IO (Network IO 스레드가 하는일)

그리고 연결된 후에 하는일(Worker 스레드가 하는일)로 나눌수 있는데요...


스레드를 여러개 만들어서 작업을 하게 됩니다.


여기서 서버 아키텍쳐를 어떻게 짜느냐에 따라서 달라지는데요.


왜 스레드를 구분짓나면 만약에 어떤 작업을 위해서 스레드들이 바쁘면 클라이언트에서 연결이 안됩니다.

때로는 클라이언트에서 전송한 데이타를 읽지 못하겠죠..


그래서 클라이언트에서 연결을 요청한다던지 데이타 송수신을 하는 스레드는 최대한 빠르게 작업을 종료해야 되며 시간이 오래 걸리는 작업 Worker 스레드로 맡기게 됩니다.


데이타를 읽으면 큐에 넣고 바로 리턴해버려야 겠죠.


이런 매커니즘이 기본인데 서버마다 다른 부분이 있겠죠.





11. 쓰레드 풀, 메모리 풀


쓰레드는 CPU 코어 개수에 따라 프로그램 로직에 따라 적정숫자를 지정해야 합니다.


어쨋든 무한하지 않기 때문에 그 숫자만큼 스레드풀에 스레드를 담아놓고 재활용하여 사용하게 됩니다.


메로리 풀은 메모리를 생성, 파괴하는 시간이 오래 걸리기 떄문에 미리 메모리를 생성해놓고 재활용하여 사용합니다.


둘다 검색해보면 많이 나올듯..






일단 적어놓고 생각나면 더 쓰던지 해야 겠습니다.


평소에 지식을 정리해 놓지 않으니 적을때 역시 힘드네요...


다음글은 언어에 대한 얘기입니다.


이것과 연관된 4. Block, None Block, 동기, 비동기, 멀티스레드, 배타제어 


를 쓰는게 좋겠네요..