====== node.js 에코 서버와 클라이언트 제작해보기 ======
node.js 기반의 에코 서버, 파이썬 기반으로 대응되는 간단한 콘솔 클라이언트를 제작해봅니다.
===== 시놉시스 =====
==== 서버 ====
- 클라이언트가 접속하면 접속하였다는 메시지를 출력합니다.
- 클라이언트로부터 메시지를 받으면 받은 메시지를 그대로 출력하고, 클라이언트로 되돌려 보냅니다.
- 클라이언트로부터 접속이 종료되면 종료 메시지를 출력합니다.
==== 클라이언트 ====
- 서버에 접속하면 접속했다는 메시지를 출력합니다.
- 서버에 메시지를 보냅니다. 받은 메시지는 서버에 전달되었다가, 그대로 서버로부터 전달받습니다.
- 클라이언트는 간단하게 C, 파이썬으로 구현해봅니다.
===== 서버측 구현=====
// 필요한 객체를 선언합니다.
var net = require('net');
var port = 9000;
// 소켓에 필요한 핸들러는 이 곳에 미리 선언합니다.
function server_handler(socket)
{
socket.on('connect', onSocketConnect);
//socket.on('data', onSocketData);
socket.on('end', onSocketEnd);
socket.on('timeout', onSocketTimeOut);
socket.on('drain', onSocketDrain);
socket.on('error', onSocketError);
socket.on('close', onSocketClose);
// socket에 효과적으로 접근하기 위해서는 이 방법이 효과적입니다.
socket.on('data', function (buffer) {
onSocketData(socket, buffer)
});
}
// net.Socket event handlers
function onSocketConnect()
{
console.log('onSocketConnect: connection established');
}
function onSocketData(socket, buffer)
{
var msg = 'ECHO: ' + buffer;
console.log('onSocketData: data received');
process.stdout.write(msg);
if(socket.write(msg))
console.log('onSocketData: data echoed successfully');
else
console.log('onSocketData: some error occured :(');
}
// emitted when the other side of the socket sends a FIN packet
function onSocketEnd()
{
console.log('onSocketEnd: a client sent a FIN packet.');
}
function onSocketTimeOut()
{
console.log('onSocketTimeOut: called.');
}
// when the write buffer becomes empty
function onSocketDrain()
{
console.log('onSocketDrain: called.');
}
function onSocketError(err)
{
console.log('onSocketError: called.');
}
function onSocketClose(had_error)
{
console.log('onSocketClose: connection closed.');
if(had_error)
{
console.log('onSocketClose: some error happend :(');
}
else
{
console.log('onSocketClose: no error :)');
}
}
// net.Server event handler
function onServerListening()
{
console.log('onServerListening: listening on port ' + port);
console.log('Press \'x\' to exit...');
}
function onServerConnection(socket)
{
var ip = socket.remoteAddress;
var port = socket.remotePort;
console.log('onServerConnection: connection received from '+ip+':'+port);
}
function onServerClose()
{
console.log('onServerClose: server closed');
process.exit(0);
}
function onServerError(err)
{
console.log('onServerError: called');
}
function onStdinData(server, data)
{
console.log('onStdinData: '+data);
console.log('onStdinData: length '+data.length);
if(data == 'x\n')
{
console.log('onStdinData: termination command received');
server.close();
process.exit(0);
}
}
function onStdinEnd()
{
console.log('onStdinEnd: called');
}
////////////////////////////////////////////////////////////////////////////////
// Beginning
// argument parsing
if (process.argv.length != 3)
{
console.log('Usage: node echo_server.js ');
process.exit(0);
}
else
{
port = process.argv[2]
}
// 서버 생성
var server = net.createServer(server_handler);
// 서버의 이벤트를 설정합니다.
// server.on('data', );
server.on('listening', onServerListening);
server.on('connection', onServerConnection);
server.on('close', onServerClose);
server.on('error', onServerError);
// 서버는 대기
server.listen(port);
// stdin 활성화
process.stdin.resume();
process.stdin.on('data', function(data){onStdinData(server, data);});
process.stdin.on('end', onStdinEnd);
==== 사용법 ====
node echo_server.js 9000
===== 클라이언트 측 스크립트 =====
// 필요한 객체를 선언합니다.
var net = require('net');
// net.Socket event handlers
function onSocketConnect()
{
console.log('onSocketConnect: connection established');
}
function onSocketData(socket, buffer)
{
console.log('onSocketData: data received');
process.stdout.write(buffer);
}
// emitted when the other side of the socket sends a FIN packet
function onSocketEnd()
{
console.log('onSocketEnd: a client sent a FIN packet.');
}
function onSocketTimeOut()
{
console.log('onSocketTimeOut: called.');
}
// when the write buffer becomes empty
function onSocketDrain()
{
console.log('onSocketDrain: called.');
}
function onSocketError(err)
{
console.log('onSocketError: called.');
}
function onSocketClose(had_error)
{
console.log('onSocketClose: connection closed.');
if(had_error)
{
console.log('onSocketClose: some error happend :(');
}
else
{
console.log('onSocketClose: no error :)');
}
process.exit(0);
}
function onStdinData(socket, data)
{
socket.write(data);
console.log('onStdinData: data sent');
}
////////////////////////////////////////////////////////////////////////////////
// Beginning
// argument parsing
if (process.argv.length != 4)
{
console.log('Usage: node echo_client.js ');
process.exit(0);
}
var host = process.argv[2];
var port = process.argv[3];
// 소켓 생성
var options = {'port': port, 'host': host};
var socket = net.createConnection(options);
// 핸들러 설정
socket.on('connect', onSocketConnect);
socket.on('end', onSocketEnd);
socket.on('timeout', onSocketTimeOut);
socket.on('drain', onSocketDrain);
socket.on('error', onSocketError);
socket.on('close', onSocketClose);
// socket에 효과적으로 접근하기 위해서는 이 방법이 효과적입니다.
socket.on('data', function (buffer) {
onSocketData(socket, buffer)
});
// stdin 활성화
process.stdin.resume();
process.stdin.on('data', function(data){onStdinData(socket, data);});
==== 사용법 ====
node echo_client.js 127.0.0.1 9000