[C# Winform 채팅 프로그램 개발 002] TCP/IP 통신 프로토콜 정의서
1. 개요
본 문서의 목적은 채팅프로그램 서버와 클라이언트 간의 통신 방법을 정의합니다.
1.1. 통신 규격
서버,클라이언트간 통신은 TCP/IP 통신을 따른다.
(1) Server : 채팅 서버
(2) Client : Client(API를 이용하여 접속하는 클라이언트)
(3) JSON 인코딩
- JSON 인코딩은 UTF-8 을 사용
(4) 기본 포트는 6666을 사용하며 Setting 창에서 변경할 수 있다.
1.2. 데이터 표현 방식
각 패킷의 헤더는 C# 구조체 형태로 정의하고 데이터는 JSON 형식을 사용 합니다.
(주의 : 각 구조체의 packing alignment는 1byte로 한다. #pragma pack( push, 1 )를 사용해야함)
| 타입 | 크기 | 설명 |
| BYTE | 1 | 1 바이트 크기를 가진 정수형 (범위: 0~255, unsigned char) |
| CHAR | 1 | 1 바이트 크기를 가진 정수형 (범위: -128~127, char) |
| Short | 2 | 2 바이트 크기를 가진 정수형 (범위: -32,768~32,768) |
| Int | 4 | 4 바이트 크기를 가진 정수형 (범위: -2,147,483,648 ~ 2,147,483,647, unsigned int) |
| UINT | 4 | 4 바이트 크기를 가진 정수형 (범위: 0~4,294,967,295, unsigned int) |
| Long | 8 | 8 바이트 크기를 가진 정수형 (범위: -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,808) |
| FLOAT | 4 | 4 바이트 크기를 가진 부동 소수점 (float) |
| DOUBLE | 8 | 8 바이트 크기를 가진 부동 소수점 (double) |
2. Protocol Designs
2.1. Packet 구조
각 패킷은 아래 그림과 같이 패킷 헤더(Packet Header)와 패킷 데이터(Packet data payload)로 구성된다. (단, 경우에 따라서 패킷 헤더만 전송될 수도 있다.)

2.2. Packet Header
패킷 헤더는 아래와 같이 바이트 크기를 가진다.
struct PacektHeader
{
BYTE prefix[3]; // 패킷 구분자 "REX"
BYTE OPCODE; // 명령 코드
UINT Length; // body packet 길이
BYTE Reserve[8];
};
l prefix : Center 패킷 임을 구분하기 위한 구분자. 항상 ASCII 문자 “RXMG”.
l OPCODE : 패킷의 동작을 정의하는 명령 코드 (아래 명령 코드표 참고)
l Length : body Packet의 길이
2.3. Packet Data
l 패킷 데이터는 JSON 구조를 갖는다
l JSON 데이터는 UTF-8으로 인코딩 한다
l 한 Packet은 1400byte를 기준으로 한다. 대용량 시 1400byte 씩 분할하여 전송한다.
3. 코드 정의
3.1. 명령 코드 정의
채팅프로그램에서 사용되는 세부 프로토콜은 다음과 같다
| OPCODE | 설명 | 전송 주기 | 요청 필요 여부 | 통신방향 |
| 0x01 | 채팅 전송 | 채팅 발송 시 | X | C <-> S |
| 0x02 | 채팅 ACK 전송 | 채팅 수신 시 | X | C <-> S |
| 0x03 | 이미지 파일 전송 | 이미지 파일 발송 시 | X | C <-> S |
| 0x04 | 이미지 ACK 전송 | 이미지 파일 수신 시 | X | C <-> S |
| 0x05 | 대용량 파일 전송 | 대용량 파일 발송 시 | X | C <-> S |
| 0x06 | 대용량 파일 전송 | 대용량 파일 수신 시 | X | C <-> S |
4. 패킷 데이터 정의
4.1. 채팅 (OPCODE = 0x01)
서버 및 클라이언트에서 채팅을 발송할 시에는 채팅 코드를 전달하여 메시지를 구분하여 처리합니다.
l 전송 메시지 구성(Client <-> Server)
| 이름 | 타입 | 길이 | 설명 |
| PREFIX | BYTE | 3 | 패킷 구분자 “REX” |
| OPCODE | BYTE | 1 | 0x01 |
| Length | UINT | 4 | BodyPacket Byte Length 값 |
| Reserve | BYTE | 8 | |
| Data | |||
| { “date” : “2024-05-16 11:33:21”, “nickname” : “User”, “message” : “안녕” } |
|||
| Data 설명 | |||
| 이름 | 타입 | 길이 | 설명 |
| date | String | 채팅 발송 시간 값. 형식: yyyy-MM-dd HH:mm:ss | |
| nickname | String | 발송자의 닉네임 | |
| message | String | 발송자 채팅 메세지 | |
4.2. 채팅 ACK (OPCODE = 0x02)
채팅 수신 완료 시, Ack 값을 송신합니다.
l 전송 메시지 구성(Client <-> Server)
| 이름 | 타입 | 길이 | 설명 |
| PREFIX | BYTE | 3 | 패킷 구분자 “REX” |
| OPCODE | BYTE | 1 | 0x02 |
| Length | UINT | 4 | BodyPacket Byte Length 값 |
| Reserve | BYTE | 8 | |
| Data | |||
| { “ack” : 0 } |
|||
| Data 설명 | |||
| 이름 | 타입 | 길이 | 설명 |
| ack | int | 8 | 0 송신 성공 1 HeaderPacket 없음 2 Header의 length값과 body length 값 불일치 3 예외처리 오류 발생 |
4.3. 이미지 파일 (OPCODE = 0x03)
서버 및 클라이언트에서 이미지 파일을 발송할 시에는 이미지 코드를 전달하여 메시지를 구분하여 처리합니다. 이미지 파일 OPCODE 송신 시, 이미지파일 다운로드 후 Image Viewer 통해 해당 이미지를 보여줍니다.
l 전송 메시지 구성(Client <-> Server)
| 이름 | 타입 | 길이 | 설명 |
| PREFIX | BYTE | 3 | 패킷 구분자 “REX” |
| OPCODE | BYTE | 1 | 0x03 |
| Length | UINT | 4 | BodyPacket Byte Length 값 |
| Reserve | BYTE | 8 | |
| Data | |||
| { “date” : “2024-05-16 11:33:21”, “nickname” : “User”, “imagefile” : //Base64String 형식의 이미지파일 } |
|||
| Data 설명 | |||
| 이름 | 타입 | 길이 | 설명 |
| date | String | 채팅 발송 시간 값. 형식: yyyy-MM-dd HH:mm:ss | |
| nickname | String | 발송자의 닉네임 | |
| imagefile | String | 발송하는 이미지 파일을 Base64string으로 변환한 값 | |
4.4. 이미지파일 ACK (OPCODE = 0x04)
이미지파일 수신 완료 시, Ack 값을 송신합니다.
l 전송 메시지 구성(Client <-> Server)
| 이름 | 타입 | 길이 | 설명 |
| PREFIX | BYTE | 3 | 패킷 구분자 “REX” |
| OPCODE | BYTE | 1 | 0x04 |
| Length | UINT | 4 | BodyPacket Byte Length 값 |
| Reserve | BYTE | 8 | |
| Data | |||
| { “ack” : 0 } |
|||
| Data 설명 | |||
| 이름 | 타입 | 길이 | 설명 |
| ack | int | 8 | 0 송신 성공 1 HeaderPacket 없음 2 Header의 length값과 body length 값 불일치 3 예외처리 오류 발생 |
4.5. 대용량 파일 (OPCODE = 0x05)
서버 및 클라이언트에서 대용량 파일을 발송할 시에는 대용량 코드를 전달하여 메시지를 구분하여 처리합니다.
l 전송 메시지 구성(Client <-> Server)
| 이름 | 타입 | 길이 | 설명 |
| PREFIX | BYTE | 3 | 패킷 구분자 “REX” |
| OPCODE | BYTE | 1 | 0x01 |
| Length | UINT | 4 | BodyPacket Byte Length 값 |
| Reserve | BYTE | 8 | |
| Data | |||
| { “date” : “2024-05-16 11:33:21”, “nickname” : “User”, file } |
|||
| Data 설명 | |||
| 이름 | 타입 | 길이 | 설명 |
| date | String | 채팅 발송 시간 값. 형식: yyyy-MM-dd HH:mm:ss | |
| nickname | String | 발송자의 닉네임 | |
| file | String | 대용량 파일 변환 | |
4.6. 대용량 파일 ACK (OPCODE = 0x06)
대용량 파일 수신 완료 시, Ack 값을 송신합니다.
l 전송 메시지 구성(Client <-> Server)
| 이름 | 타입 | 길이 | 설명 |
| PREFIX | BYTE | 3 | 패킷 구분자 “REX” |
| OPCODE | BYTE | 1 | 0x02 |
| Length | UINT | 4 | BodyPacket Byte Length 값 |
| Reserve | BYTE | 8 | |
| Data | |||
| { “ack” : 0 } |
|||
| Data 설명 | |||
| 이름 | 타입 | 길이 | 설명 |
| ack | int | 8 | 0 송신 성공 1 HeaderPacket 없음 2 Header의 length값과 body length 값 불일치 3 예외처리 오류 발생 |