node.js tcp chatting server with QT client
node.js로 구현한 채팅 서버 및 QT로 GUI를 꾸민 클라이언트이다.
사용자 등록, 로그인, 대화상대 추가/삭제, 로그인/아웃 알림 및 메시지 전달 기능이 구현되어 있다.
Current features:
enroll user
add/remove friend
login and retrieve my friend list
notify logged in/out
deliver chat message
Server
net, Buffer module을 이용해서 작성되었다. 클라이언트와 주고받는 패킷의 정의는 다음과 같다.
The Packet format is : binary data + string
4 byte header (means a length of following message) + message
The message format is :
string|(delimiter)...
제일 먼저 32비트 정수가 포함되고 이후에는 문자열로 구성된 양식이다. 헤더와 메시지를 구분하는 별도 구분은 없다. 문자열의 길이는 이 32비트 정수에 설정 된다. 메시지의 형식은 먼저 사용 목적이 나오고 이후 구분자로 구분된 데이터들이 전송된다. 예를 들어 로그인의 경우라면 전달되는 전체 데이터는 다음과 같게 된다.
ex) Login message
4byte_integerLOGIN|SomeUserId|SomePassWord~
즉, 바이너리 데이터와 문자열이 포함되는 형식인데, 결국 다음과 같은 C 구조체가 전송되는 것과 같다.
This can be described as a C structure like this :
typedef struct _PACKET_LOGIN
{
unsigned int nLen; //4byte, contains 34
char szMSg [30];
} PACKET_LOGIN;
이러한 구조체 데이터에 nLen 에는 문자열의 길이 (30)이 설정되고 szMSg 에는 "LOGIN|someUserId|SomePassWord~" 문자열이 담겨져서 node.js 서버로 전송되는것과 같다. 그러므로 전체 데이터의 길이는 헤더에 설정된 메시지 길이(30 byte) + 헤더 자체의 길이 (4byte) = 34 byte가 된다.
인터넷에서는 echo 서버, 혹은 단순히 클라이언트의 데이터를 받는 즉시 브로드캐스팅하는 예제를 볼수 있다. 하지만 tcp의 메시지 경계 없음으로 인한
데이터 fragmentation을 고려해줘야 제대로 동작하는 서버를 작성할수 있다. 이 때문에 전달되는 데이터가 완전한 하나의 패킷이 될때, 해당 처리를 해주고 만약 기대하는 길이만큼 전송이 다 되지 않았다면, 지금까지 받은 데이터를 누적시키는 작업이 필요하다.
전달되는 데이터가 모두 문자열이라면, 일반 변수를 사용해서도 가능하겠지만, 지금 구현하는것은 헤더부분이 32비트 정수형이기 때문에 (즉 바이너리 데이터 + 스트링 의 혼합) 뭔가 다른 방법이 필요하다. 이때 node.js 가 제공하는 Buffer 모듈을 사용하면 문자열 데이터 뿐만 아니라, 정수형 데이터도 처리가 가능하다.