[오늘의 코딩테스트]
추후 추가 예정
[오늘 한일]
▶ TCP 서버 이해
- TCP 서버와 클라이언트의 이해
TCP 서버와 클라이언트의 이해에 대한 학습을 하였다.
import net from 'net';
import { readHeader, writeHeader } from './utils.js';
import { HANDLER_ID, MAX_MESSAGE_LENGTH, TOTAL_LENGTH_SIZE } from './constants.js';
import handlers from './handlers/index.js';
const PORT = 5555;
const server = net.createServer((socket) => {
console.log(`Client connected: ${socket.remotePort}`);
socket.on('data', (data) => {
const buffer = Buffer.from(data);
const { handlerId, length } = readHeader(data);
console.log(`handlerId: ${handlerId}`);
console.log(`length: ${length}`);
if (length > MAX_MESSAGE_LENGTH) {
console.error(`Error: Message length ${length}`);
socket.write(`Error: Message too long`);
socket.end();
return;
}
const handler = handlers[handlerId];
if (!handler) {
console.error(`Error: No handler found for ID ${handlerId}`);
socket.write(`Error: Invalid handler ID ${handlerId}`);
socket.end();
return;
}
const headerSize = TOTAL_LENGTH_SIZE + HANDLER_ID; //총 헤더 사이즈 = 6
const message = buffer.slice(headerSize);
console.log(`client에게 받은 message: ${message}`);
const responseMessage = handler(message);
const responseBuffer = Buffer.from(responseMessage);
const header = writeHeader(responseBuffer.length, handlerId);
const packet = Buffer.concat([header, responseBuffer]);
socket.write(packet);
});
socket.on('end', () => {
console.log(`Client disconnected: ${socket.remoteAddress}: ${socket.remotePort}`);
});
socket.on('error', (err) => {
console.log(`Socket error, ${err}`);
});
});
server.listen(PORT, () => {
console.log(`Echo Server listening on port ${PORT}`);
console.log(server.address());
});
서버 코드가 다음과 같이 켜졌다면, 서버는 listen으로 서버를 키고 socket에 클라이언트 정보가 들어오길 기다린다.
import net from 'net';
import { readHeader, writeHeader } from './utils.js';
import { HANDLER_ID, MAX_MESSAGE_LENGTH, TOTAL_LENGTH_SIZE } from './constants.js';
const HOST = 'localhost';
const PORT = 5555;
const client = new net.Socket();
client.connect(PORT, HOST, () => {
console.log('Connected to the server...');
const message = 'hello';
const buffer = Buffer.from(message);
const header = writeHeader(buffer.length, 11);
const packet = Buffer.concat([header, buffer]);
client.write(packet);
});
client.on('data', (data) => {
const buffer = Buffer.from(data);
const { handlerId, length } = readHeader(data);
console.log(`handlerId: ${handlerId}`);
console.log(`length: ${length}`);
const headerSize = TOTAL_LENGTH_SIZE + HANDLER_ID; //총 헤더 사이즈 = 6
const message = buffer.slice(headerSize);
console.log(`server에게 받은 message: ${message}`);
});
client.on('close', () => {
console.log(`Connection closed`);
});
client.on('error', (err) => {
console.log(`Client error: ${err}`);
});
클라이언트가 다음과 같이 켜진다.클라이언트는 켜지는 동안 connect를 통해 log로 클라이언트가 연결되었음을 알림고, message 인 hello를 buffer에 담고 헤더의 정보에는 writeHeader라는 utils에서 만든 함수를 통해 buffer의 길이와 임의로 정한 핸들러ID 11을 header라는 상수에 담고, 해당 buffer와 header의 정보를 합쳐서 packet에 넣은다음 write를 통해 서버에 hello라는 메시지 버퍼와 헤더 정보를 전달한다. ->
이제 서버에서는 socket.on으로 클라이언트에서 보낸 정보를 확인하고 헤더인 메시지의 길이와, 핸들러 ID를 분해한뒤 메시지의 길이가 지정한 메시지의 총 길이 1024를 넘는다면 에러를 띄우고 종료시키고, handler아이디에 올바른 값이 전달되지 않아도 종료시킨다. 핸들러 ID가 잘 들어갔다면 해당하는 핸들러를 실행 시키느데 11번 같은경우에는 보낸 데이터를 역순으로 바꾸는 핸들러이다. 그래서 받은 정보 hello를 역순으로 뒤집고 다시 헤더에 length와 handlerID를 보내고 write를 통해 클라이언트에 다시보낸다. ->
그럼 클라이언트에 'data'라는 이벤트에 들어가게 되고 해당 이벤트를 통해 서버에게서 받은 메시지를 출력한다.
다음과 같이 TCP가 크게 돌아가는 방법, 서버에서 가공한 데이터를 클라이언트에 전달하는 방법, 핸들러와 길이 LENGTH등을 함께 버퍼에 어떤식으로 묶어서 넣는지에 대한 이해등을 할 수 있었다.
[하루 요약]
생각보다 TCP가 복잡하게 느껴져서 하나하나 강의를 뜯어보면서 확인했는데 많이 어려움이 느껴진다. 그래도 꼭 공부해야하는 부분이기 때문에 열심히 학습해야겠다고 다시 느꼈다!
'코딩 > TIL' 카테고리의 다른 글
[TIL] TCP서버 제작 개인 과제 진행 (0) | 2024.07.08 |
---|---|
[TIL] js server 유니티 연동 (1) | 2024.07.03 |
[TIL] 게임서버의 이동 연출 (선형보간, 외삽법) (0) | 2024.06.27 |
[TIL] Socket.io 의 on 과 emit의 이해 (0) | 2024.06.26 |
[TIL] 모의 면접 대비 공부 (0) | 2024.06.25 |