[Node.js] TCP/IP 소켓 통신하기
![[Node.js] TCP/IP 소켓 통신하기](/content/images/size/w1920/2024/12/nodejspng-1.png)
Node.js에서 TCP/IP 사용하는 법 🌐✨
1. TCP/IP란 무엇인가? 🤔
- *TCP/IP(Transmission Control Protocol/Internet Protocol)**는 인터넷과 네트워크에서 데이터를 송수신하기 위한 핵심 프로토콜이다. TCP는 데이터의 신뢰성을 보장하며, IP는 데이터를 목적지로 전달하는 역할을 한다.
📚 TCP/IP의 주요 특징
- 신뢰성 보장: 데이터 패킷의 전송과정에서 손실이 발생하면 자동으로 재전송한다.
- 연결 지향: 데이터를 전송하기 전에 송신자와 수신자 간의 연결을 설정한다.
- 순차적 데이터 전달: 데이터를 올바른 순서로 수신할 수 있도록 보장한다.
2. TCP/IP의 동작 원리 🛠️
TCP/IP는 4계층 네트워크 모델을 기반으로 동작한다:
- 응용 계층(Application Layer): 사용자 애플리케이션이 네트워크를 사용할 수 있게 한다. (예: HTTP, FTP)
- 전송 계층(Transport Layer): 신뢰성 있는 데이터 전송을 담당한다. (예: TCP, UDP)
- 인터넷 계층(Internet Layer): 데이터 패킷을 목적지로 전달한다. (예: IP)
- 네트워크 접근 계층(Network Access Layer): 물리적 데이터 전송을 수행한다.
3. Node.js에서 TCP/IP 통신 구현하기 🛠️
net
모듈이란?
Node.js에서 TCP 통신을 구현하기 위해 제공되는 기본 내장 모듈이다.
이 모듈은 클라이언트와 서버 간 데이터 송수신을 가능하게 하며, 다음과 같은 주요 메서드를 제공한다
npm install net
TCP/IP 모듈 구현 및 코드 설명 🧩
1) TCP 연결 초기화: connect
함수
이 함수는 클라이언트가 서버에 연결을 설정하는 역할을 한다.
import net from 'net';
import { logger } from '#util/logger.js';
let client = null;
let isConnected = false;
/**
* TCP 연결 초기화
* @param {string} host - 서버 IP 주소
* @param {number} port - 서버 포트 번호
* @returns {Promise<void>}
*/
export const connect = async (host, port) => {
return new Promise((resolve, reject) => {
client = new net.Socket(); // 소켓 객체 생성
client.connect(port, host, () => {
isConnected = true; // 연결 상태 플래그 설정
logger.info(`[tcp-connect] Connected to ${host}:${port}`);
resolve(); // 연결 성공 시 resolve 호출
});
// 연결 에러 처리
client.on('error', (error) => {
logger.error(`[tcp-connect] Connection error: ${error.message}`);
isConnected = false; // 연결 상태 플래그 해제
reject(error); // 연결 실패 시 reject 호출
});
// 연결 종료 이벤트
client.on('close', () => {
logger.info(`[tcp-connect] Connection closed`);
isConnected = false; // 연결 상태 플래그 해제
});
});
};
설명
net.Socket
객체 생성:- TCP 클라이언트를 초기화한다.
connect
메서드 호출:- 서버의
host
와port
를 지정하여 연결을 시도한다. - 연결이 성공하면
resolve()
를 호출하여 연결 상태를 업데이트한다.
- 서버의
- 에러 처리:
- 연결 도중 에러가 발생하면
error
이벤트 핸들러가 호출되고, 연결 상태를 플래그(isConnected
)로 표시한다.
- 연결 도중 에러가 발생하면
- 종료 처리:
- 서버 또는 클라이언트 측에서 연결이 종료되면
close
이벤트가 발생한다.
- 서버 또는 클라이언트 측에서 연결이 종료되면
2) TCP 데이터 송수신: sendAndReceiveData
함수
서버로 데이터를 전송하고, 서버로부터의 응답을 대기한다.
/**
* 데이터를 전송하고 응답을 대기
* @param {Buffer|string} data - 전송할 데이터
* @param sendEncoding - 데이터 송신 인코딩
* @param receiveEncoding - 데이터 수신 인코딩
* @returns {Promise<string>} - 수신된 데이터
*/
export const sendAndReceiveData = async (data, sendEncoding, receiveEncoding) => {
if (!isConnected) {
throw new Error(`[tcp-sendAndReceiveData] Client is not connected`);
}
return new Promise((resolve, reject) => {
// 데이터 송신
client.write(data, (error) => {
if (error) {
logger.error(`[tcp-sendAndReceiveData] Error sending data`);
reject(error);
} else {
logger.info(`[tcp-sendAndReceiveData] Data sent: ${data.toString(sendEncoding)}`);
}
});
// 데이터 수신 이벤트 등록
const onData = (data) => {
try {
logger.info(`[tcp-sendAndReceiveData] Data received: ${data.toString(receiveEncoding)}`);
client.off('data', onData); // 리스너 해제
resolve(data.toString(receiveEncoding)); // 수신된 데이터를 resolve
} catch (error) {
client.off('data', onData); // 오류 발생 시 리스너 해제
logger.error(`[tcp-sendAndReceiveData] Error processing received data: ${error.message}`);
reject(error); // 에러 발생 시 reject 호출
}
};
client.on('data', onData); // 데이터 수신 이벤트 핸들러 등록
});
};
설명
- 연결 상태 확인:
- TCP 연결이 활성화되지 않았다면 오류를 발생시킨다.
- 데이터 송신 (
write
):- 클라이언트가 서버로 데이터를 전송한다.
- 송신이 성공하면 로그를 남긴다.
- 데이터 수신 (
on('data')
):- 서버가 데이터를 응답하면 해당 데이터를 처리한다.
- 데이터 처리 후 이벤트 리스너(
onData
)를 해제하여 메모리 누수를 방지한다.
- 오류 처리:
- 데이터 처리 도중 오류가 발생하면 리스너를 해제하고
reject
로 에러를 반환한다.
- 데이터 처리 도중 오류가 발생하면 리스너를 해제하고
3) TCP 연결 종료: disconnect
함수
TCP 연결을 안전하게 종료한다.
/**
* TCP 연결 종료
* @returns {Promise<void>}
*/
export const disconnect = async () => {
if (!isConnected) {
logger.info(`[tcp-disconnect] Client is not connected`);
return;
}
return new Promise((resolve, reject) => {
client.end(() => {
logger.info(`[tcp-disconnect] Connection ended`);
isConnected = false; // 연결 상태 플래그 해제
resolve(); // 연결 종료 성공
});
// 연결 종료 중 에러 처리
client.on('error', (err) => {
logger.error(`[tcp-disconnect] Error while disconnecting: ${err.message}`);
reject(err); // 에러 발생 시 reject
});
});
};
설명
- 연결 상태 확인:
- 연결이 없는 경우, 추가 작업을 수행하지 않고 종료한다.
end
메서드 호출:- 서버와의 연결을 안전하게 종료한다.
- 에러 처리:
- 연결 종료 중 에러가 발생하면
reject
를 호출한다.
- 연결 종료 중 에러가 발생하면
4. 실제 사용 예제
- 서버 연결:
connect
함수로 서버와의 연결을 설정.
- 데이터 송수신:
sendAndReceiveData
함수로 데이터를 송신하고 응답을 대기.
- 연결 종료:
disconnect
함수로 TCP 연결을 안전하게 종료.
// TCP-IP를 사용하는 서비스단 구축 예제
import * as socket from '#module/tcp_module.js';
import { logger } from '#util/logger.js';
import { sleep } from '#util/wb_lib.js';
export const tcpService = async (tcpData, onErrorCallback) => {
try {
const tcpInfo= {
connIp: tcpData.connIp,
connPort: tcpData.connPort
};
await socket.connect(displayInfo.connIp, displayInfo.connPort);
await getTcpDevice();
await sleep(500);
} catch (error) {
logger.error(`[tcpService] Error!`);
if (onErrorCallback) {
onErrorCallback(error);
}
} finally {
await socket.disconnect();
}
};
const getTcpDevice = async () => {
try {
const cmd = Buffer.from([0x02, 0xC0, 0x01, 0x02, 0x03, 0x00)
await socket.sendAndReceiveData(cmd, 'hex', 'hex');
logger.info(`[getTcpDevice] Success`);
} catch (error) {
logger.error(`[getTcpDevice] Error!`);
throw error;
}
};
5. 결론 🏁
TCP/IP는 인터넷과 네트워크 통신에서 가장 중요한 프로토콜로, 신뢰성 있는 데이터 전송을 제공한다. Node.js의 net
모듈을 활용하면 TCP 기반의 네트워크 애플리케이션을 쉽게 구현할 수 있다.
댓글