Node 강의/주특기 플러스

1-1 TCP Echo 서버 세팅하기

kagan-draca 2024. 10. 17. 15:04

Vscode에서 해당 디렉토리에 접근한다.

 

해당 디렉토리에서 터미널을 열고

 

yarn init -y

 

를 입력한다.

 

package.json

 

파일들어가 

 

"type" : "module"

을 추가한다.

 

다시 터미널로 돌아와

yarn add - D prettier

로 패키지를 받고,

 

.prettierrc 파일을 만들어줍니다.

 

.prettierrc 파일에는 아래와 같이 복사해 붙여 넣어줍니다.

{
  "singleQuote": true,
  "semi": true,
  "useTabs": false,
  "tabWidth": 2,
  "trailingComma": "all",
  "printWidth": 100,
  "arrowParens": "always",
  "orderedImports": true,
  "bracketSpacing": true,
  "jsxBracketSameLine": false
}

 

1. TCP Echo 서버 만들기

server.js 파일을 만들고

 

server.js 파일에 

import net from 'net';

 

모듈을 import해 옵니다.

 

net 모듈은 Node.js에서 제공하는 모듈로 기본적인 TCP 서버를 제공해줍니다.

 

이제 서버를 만들기 위해

const server = net.createServer((socket)=>{

})

 

위와 같이 작성해줍니다.

 

WebServer와 달리 TCP Server는 socket 통신을 하기 때문에

매개변수로 socket을 받아올 수 있고 Client들이 socket을 통해 접속을 하게 됩니다.

 

그래서, socket을 통해 Client가 어떤 주소, 어떤 포트를 통해 접속하고 있는지

  console.log(`Client connected : ${socket.remoteAddress} : ${socket.remotePort}`);
  // 소켓으로 접속한 유저 주소와 포트 주소

  

console.log()로 확인할 수 있습니다.

 

현재 우리는 서버를 만들기만 할 뿐 서버를 실행시키지는 않은 상태 입니다.

const PORT = 5555;
// 서버 실행
server.listen(PORT, () => {
  console.log(`Echo Server listening on port ${PORT}`);
  console.log(server.address());
});

 

server.listen()과 PORT로 서버를 실행시켜 줍니다.

 

그리고, 서버의 주소와 포트를 console로 출력해줍니다.

 

터미널에 

 

node server.js 실행시켜 보면

 

위와 같이 IPv6 주소 PROT : 5555로 서버가 실행된 것을 확인할 수 있습니다.

 

2. Client 만들기

Client.js 파일을 만들고

import net from 'net';


서버와 마찬가지로 net 모듈을 import 해줍니다.

 

그 후, 

const HOST = 'localhost';
const PORT = '5555';

 

접속할 URL 정보들을 입력해주고,

 

const client = new net.Socket();
//          net Class 객체의 Socket 메서드로 소켓을 만든다.

socket을 만들어줍니다.

 

client.connect(PORT, HOST, () => {
  console.log('Connected To The Server...');
});

그리고, 5555 포트의 localhost 서버로 접속하겠다고 명시해줍니다.

 

터미널에서 node client.js로 client.js를 실행시키면,

 

클라이언트에서는 서버와 연결됐다를 출력해주고,

 

서버에서는

위와 같이 클라이언트가 서버에 접속했다고 출력이 됩니다.

현재는 localhost 환경에서 접속을 시도했기 때문에 ip주소가 없는 상태 입니다.

 

3. Client, Server.js에서 Event 만들기

1) Server.js

const server = net.createServer((socket) => {
  console.log(`Client connected : ${socket.remoteAddress} : ${socket.remotePort}`);
  // 소켓으로 접속한 유저 주소와 포트 주소

});
// 서버 생성

 

Client가 서버에 접속한 이후 Client의 행동에 따른 Event를 처리하는 과정을 만들어보겠습니다.

 

const server = net.createServer((socket) => {
  console.log(`Client connected : ${socket.remoteAddress} : ${socket.remotePort}`);
  // 소켓으로 접속한 유저 주소와 포트 주소

  socket.on('data', (data) => {
    // 서버가 클라이언트로부터 데이터를 받을 때 마다 발생
    // data는 버퍼 형태로 제공되며, 이를 문자열로 변환하거나 원하는 형식으로 처리할 수 있다.

    console.log(data);
  });

  socket.on('end', () => {
    // 소켓의 다른 쪽에서 FIN 패킷을 보내 데이터 전송이 완료 되었음을 나타낼 때 발생
    // => 클라이언트가 더 이상 데이터를 보내지 않을 때 발생합니다.

    console.log(`Client disconnected : ${socket.remoteAddress} : ${socket.remotePort}`);
    // 해당 소켓으로 접속한 유저와 연결이 끊겼을 경우 유저 주소와 포트 주소
  });

  socket.on('error', (error) => {
    // 에러가 발생했을 때 발생합니다. 이 이벤트 이후에 close 이벤트가 호출됩니다.
    console.log(`Socket error : ${error}`);
  });
});
// 서버 생성

위와 같이 data를 받았을 때 처리하는 이벤트, 데이터 전송이 완료 됐을 때의 이벤트, error가 발생했을 때의 이벤트를 서버에 작성해보았습니다. 그럼 Client에서도 동일한 이벤트를 서버로 보낼 수 있게 구현해봅시다.

 

2) Client.js

client.on('data', (data) => {
  console.log(data);
});

client.on('close', () => {
  // 'close'는 서버와 클라이언트 양쪽의 연결이 끊겼을 경우
  // 이벤트와 달리, 양쪽 모두 닫혔음을 의미하고, 리소스 해제나 후속 작업을 처리할 때 유용하다.
  console.log('Connection Closed');
});

client.on('error', (err) => {
  console.log('Client error : ', err);
});

에 위와 같이 데이터 전송에 따른 이벤트('data'), error가 발생했을 때의 이벤트를 추가해줍니다('error').

 

서버와 다른 부분으로는 'close'인데 close는 서버와 클라이언트 양쪽의 연결이 끊겼을 경우를 의미하고,

'end'는 한 쪽의 연결이 끊겼을 때 입니다.

 

'close'는 리소스 해제나 후속 작업을 처리할 때 유용합니다.

 

add) 추가 학습 : 다른 이벤트들

 

  1. Connect

    소켓 연결이 성공적으로 설정되었을 때 발생합니다. 주로 클라이언트 측 소켓에서 사용 합니다.

    socket.on('connect', () => {
      console.log('Connected to server');
    });
  2. Drain

    쓰기 버퍼가 비워졌을 때 발생합니다. 더 많은 데이터를 써도 안전함을 의미합니다.

    socket.on('drain', () => {
      console.log('Write buffer drained');
    });
  3. lookup

    호스트 이름을 해결한 후 연결하기 전에 발생합니다. 주소 패밀리와 주소에 대한 정보를 제공합니다.

    socket.on('lookup', (err, address, family, host) => {
      console.log(`Address: ${address}, Family: ${family}`);
    });
  4. ready

    호스트 이름을 해결한 후 연결학 전에 발생합니다. 주소 패밀리와 주소에 대한 정보를 제공합니다.

    socket.on('ready', () => {
      console.log('Socket is ready');
    });
  5. timeout

    소켓이 비활성 상태로 인해 타임아웃 되었을 때 발생합니다. 타임아웃이 설정된 경우에만 관련이 있습니다.

    socket.on('timeout', () => {
      console.log('Socket timeout');
      socket.end();
    });

 

 

이제 Client와 Server가 데이터를 주고 받아 볼려고 하는 그 전에 Buffer 객체가 뭔지 잠시 살펴보겠습니다.