상세 컨텐츠

본문 제목

[Node.js] Node.js 소켓, 웹소켓, (TCP/IP),통신 관련 프로그래밍 관련

WEB/JavaScript

by AlrepondTech 2018. 10. 1. 01:28

본문

반응형

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

출처: http://nerobong2.blogspot.com/2017/01/nodejs-nodejs.html

 

 

nodejs란? 자바스크립트 기반 서버 사이드 스크립트 언어


설치방법은 따로 블로그 하지 않겟다.(매우간단함.)

설치완료 하면 node_modules 라는 폴더가 생성되고 기본 내장 js 모듈 파일들이 존재하며
require 키워드를 통해 어디서든 사용가능 하다.

단 라이브러리를 추가할때는 node_modules 폴더가 존재하는 위치에서 mpn ~~ 을 실행하길 추천한다.
테스트 os 는 윈도우 실제 적용환경은 리눅스(centOS) 였음.
아래 코드는 각각의 OS 에서 정상작동한다.

서버코드.

//websocket 객체 생성 (npm 으로 라이브러리를 추가해야한다.)
var WebSocketServer = require('websocket').server;
//http 객체 생성
var http = require('http');

//nodejs 는 스크립트 오류가 발생시 프로세스가 종료된다. 따라서 예외처리는 필수
try{
        //http 객체로부터 서버를 생성한다.
        var server = http.createServer(function (req, res) {
                //이부분은 알아서~변경
                res.writeHead(404);
res.end();
});
        //서버포트를 설정한다. 8887번포트 리슨대기 상태
        server.listen(8887, function () {

});
      
        //websocket 웹소캣 객체생성자에 위에서 생성한 server 객체를 httpServer
        //값에 셋팅 한다.
wsServer = new WebSocketServer({
httpServer: server,
autoAcceptConnections: false
});
      

        //웹소캣 이벤트 정의
wsServer.on('request', function (request) {
                

                //이부분에서 좀 해맷다. CP의 폐해
                //accept 함수 첫번째 인자 값에 연결 데이터방식에 대한 정의가 필요한듯.
                //null 일경우 모든 client 전송 데이터 연결 허용.
                //특정문자열을 입력하여 제한가능 한걸로 보임
var connection = request.accept(null, request.origin);

                //메세지 수신 이벤트
connection.on('message', function (message) {

                        //String 형태로 넘어온데이터 처리
if (message.type === 'utf8') {
     //로직
                             //ex) 헬로라는 문자열을 사용자에게 출력.
                             connection.send('hello');
                        //바이너리 데이터 처리
}else if (message.type === 'binary') {
     //로직
                        }else{
             //로직
}

});

                //사용자가 연결을 끊엇을때 이벤트 처리
connection.on('close', function (reasonCode, description) {

});
});

}catch(exception){

}

nodejs 기본 제공 하는 socket.io 기술을 사용해서 구현도 가능 하지만 클라이언트 단에
관련라이브러리 js 파일을 넣어줘야한다.

위 기본 형태는 서버와 클라이언트 1:1 통신 이며 서버가 클라이언트 들에게 모두 중개 해야하는 입장이라면 추가로직이 필요할것이다.



클라이언트 코드.


var ws = new WebSocket('ws://아이피:포트');

(ssl 적용관련 설명은 따로 올릴예정)

//웹소켓을 기본적으로 하는 미지원 브라우저도 존재한다.
if('WebSocket' in window){

ws.onopen=function(e){
console.log(e);
console.log("onopen");
}
ws.onclose=function(e){
                console.log(e);
console.log("onclose");
}
ws.onerror=function(e){
                console.log(e);
console.log("onerror");
}
ws.onmessage = function (evt) {
                console.log(e);
console.log("onerror");
};

}else{
console.log("WebSocket not supported.");
}

 

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://nerobong2.blogspot.com/2017/01/nodejs-websocket-ssl.html

 

 

[nodejs] webSocket ssl 적용.

 
사실상 소스코드는 복잡하지가 않다.
 
 
//의존모듈들 없는것을 설치
 
var https = require('https');
var fs   = require('fs');
var WebSocketServer = require('websocket').server;
 
//ca, key, cert 세가지 인자가 필요한데. 각파일의 자세한 기능은 솔직히 잘모르겟음.
 
var https_options = {
 ca: fs.readFileSync("/디렉토리/xxxx.pem 인증서정보 여겨짐"),
 key: fs.readFileSync("/디렉토리/xxxx.key 공개키정보로 여겨짐"),
 cert: fs.readFileSync("/디렉토리/xxxx.crt" 도메인정보 로 여겨짐)
};
 
//위에서 생성한 옵션을 넘겨서 https 서버를 생성하한다.
var httpsServer = https.createServer( https_options, function(request, response) {
    console.log((new Date()) + ' Received request for ' + request.url);
    response.writeHead(404);
    response.end();
});
 
//포트설정
httpsServer.listen(8887);
 
//ws 모듈이 내부적으로 없을경우 설치
var WebSocketServer = require('ws').Server;
 
//웹소켓 서버 생성
var wss = new WebSocketServer({
    server: httpsServer,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection's origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
});
 
function originIsAllowed(origin) {
  // put logic here to detect whether the specified origin is allowed.
  return true;
}
 
 
 
wss.on('connection', function connection(ws) {
 
        //.수신처리 
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
        // 발신
        ws.send('something');
});
 
일반 http 프로토콜 기반 웹소켓 서버를 생성하는것과 그렇게 큰차이는 없다. 
 
 
 
그치만 ssl에 대한 기본 적인 개념이 없다면 아마 막히는 부분이 많을 것이다.
 
ssl 통신.
 
클라이언트 측에서 https://aaa.com 요청을 보내면

1. aaa.com 도메인에 연결된 웹서버에서 인증서 정보화 공개키 정보를 담아서 클라이언트에게 전달한다.

2. 전달받은 클라이언트는 브라우저 내부적으로 인증기관정보 및 도메인 정보를 가지고 신뢰할수 있는 도메인 유무를 확인후 랜덤으로 생성 한 대칭키를 클라이언트에게 전달한다.

3. 클라이언트는 전달받은 대칭키로 데이터및 url 을 암호화 하고 대칭키를 처음에 서버로부터 받은 공개키로 또 암호화를해서 서버로 데이터를 전송한다.

4. 서버는 받은 대칭키를 개인키로 복호화하고 복호화된 대칭키로 데이터를 다시 복호화 한다.

5. 서버에서 데이터 전송시 데이터를 개인키로 암호화후 전송한고 클라이언트는 공개키로 복호화한다.


예를들면 aaa.com  에 적용된 ssl 인증서 정보로 wss://아이피:포트 웹소켓서버에 ssl을 동일 하게 적용해도 인증업체에  도메인 등록이 되어있지 않으면 통신이 불가능 하다. 따라서 인증업체에 도메인 추가를 한후 다시 인증서를 받아서 처리하거나(그다지 추천하는 방식은아님) ssl 터널링 기술을 이용해야한다. 

 

 

 

=================================

=================================

=================================

 

 

 

 

출처: https://www.npmjs.com/package/websocket

 

Installation

A few users have reported difficulties building the native extensions without first manually installing node-gyp. If you have trouble building the native extensions, make sure you've got a C++ compiler, and have done npm install -g node-gyp first.

Native extensions are optional, however, and WebSocket-Node will work even if the extensions cannot be compiled.

In your project root:

$ npm install websocket 

Then in your code:

var WebSocketServer = require('websocket').server;
var WebSocketClient = require('websocket').client;
var WebSocketFrame  = require('websocket').frame;
var WebSocketRouter = require('websocket').router;
var W3CWebSocket = require('websocket').w3cwebsocket;

Note for Windows Users

Because there is a small C++ component used for validating UTF-8 data, you will need to install a few other software packages in addition to Node to be able to build this module:

Current Features:

  • Licensed under the Apache License, Version 2.0
  • Protocol version "8" and "13" (Draft-08 through the final RFC) framing and handshake
  • Can handle/aggregate received fragmented messages
  • Can fragment outgoing messages
  • Router to mount multiple applications to various path and protocol combinations
  • TLS supported for outbound connections via WebSocketClient
  • TLS supported for server connections (use https.createServer instead of http.createServer)
    • Thanks to pors for confirming this!
  • Cookie setting and parsing
  • Tunable settings
    • Max Receivable Frame Size
    • Max Aggregate ReceivedMessage Size
    • Whether to fragment outgoing messages
    • Fragmentation chunk size for outgoing messages
    • Whether to automatically send ping frames for the purposes of keepalive
    • Keep-alive ping interval
    • Whether or not to automatically assemble received fragments (allows application to handle individual fragments directly)
    • How long to wait after sending a close frame for acknowledgment before closing the socket.
  • W3C WebSocket API for applications running on both Node and browsers (via the W3CWebSocketclass).

Known Issues/Missing Features:

  • No API for user-provided protocol extensions.

Usage Examples

Server Example

Here's a short example showing a server that echos back anything sent to it, whether utf-8 or binary.

#!/usr/bin/env node
var WebSocketServer = require('websocket').server;
var http = require('http');
 
var server = http.createServer(function(request, response) {
    console.log((new Date()) + ' Received request for ' + request.url);
    response.writeHead(404);
    response.end();
});
server.listen(8080, function() {
    console.log((new Date()) + ' Server is listening on port 8080');
});
 
wsServer = new WebSocketServer({
    httpServer: server,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection's origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
});
 
function originIsAllowed(origin) {
  // put logic here to detect whether the specified origin is allowed.
  return true;
}
 
wsServer.on('request', function(request) {
    if (!originIsAllowed(request.origin)) {
      // Make sure we only accept requests from an allowed origin
      request.reject();
      console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
      return;
    }
    
    var connection = request.accept('echo-protocol', request.origin);
    console.log((new Date()) + ' Connection accepted.');
    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log('Received Message: ' + message.utf8Data);
            connection.sendUTF(message.utf8Data);
        }
        else if (message.type === 'binary') {
            console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
            connection.sendBytes(message.binaryData);
        }
    });
    connection.on('close', function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    });
});

Client Example

This is a simple example client that will print out any utf-8 messages it receives on the console, and periodically sends a random number.

This code demonstrates a client in Node.js, not in the browser

#!/usr/bin/env node
var WebSocketClient = require('websocket').client;
 
var client = new WebSocketClient();
 
client.on('connectFailed', function(error) {
    console.log('Connect Error: ' + error.toString());
});
 
client.on('connect', function(connection) {
    console.log('WebSocket Client Connected');
    connection.on('error', function(error) {
        console.log("Connection Error: " + error.toString());
    });
    connection.on('close', function() {
        console.log('echo-protocol Connection Closed');
    });
    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log("Received: '" + message.utf8Data + "'");
        }
    });
    
    function sendNumber() {
        if (connection.connected) {
            var number = Math.round(Math.random() * 0xFFFFFF);
            connection.sendUTF(number.toString());
            setTimeout(sendNumber, 1000);
        }
    }
    sendNumber();
});
 
client.connect('ws://localhost:8080/', 'echo-protocol');

Client Example using the W3C WebSocket API

Same example as above but using the W3C WebSocket API.

var W3CWebSocket = require('websocket').w3cwebsocket;
 
var client = new W3CWebSocket('ws://localhost:8080/', 'echo-protocol');
 
client.onerror = function() {
    console.log('Connection Error');
};
 
client.onopen = function() {
    console.log('WebSocket Client Connected');
 
    function sendNumber() {
        if (client.readyState === client.OPEN) {
            var number = Math.round(Math.random() * 0xFFFFFF);
            client.send(number.toString());
            setTimeout(sendNumber, 1000);
        }
    }
    sendNumber();
};
 
client.onclose = function() {
    console.log('echo-protocol Client Closed');
};
 
client.onmessage = function(e) {
    if (typeof e.data === 'string') {
        console.log("Received: '" + e.data + "'");
    }
};

Request Router Example

For an example of using the request router, see libwebsockets-test-server.js in the test folder.

Resources

A presentation on the state of the WebSockets protocol that I gave on July 23, 2011 at the LA Hacker News meetup. WebSockets: The Real-Time Web, Delivered

 

 

 

=================================

=================================

=================================

 

 

 

출처: https://techbrij.com/node-js-tcp-server-client-promisify

 

 

Node.js: Simple TCP Server & Client and Promisify the Client

By Brij Mohan

In this post, you will see an example of simple TCP server and client in traditional javascript way and in ES6 way. Node.js has net module which provides an asynchronous network API for creating stream-based TCP or IPC servers and clients. We are going to use it to implement TCP server and client. This post is updated with Node v6.11.2.

 

 

TCP Server:

Here is an example of TCP server in Node.js:

var net = require('net');
 
// Configuration parameters
var HOST = 'localhost';
var PORT = 1234;
 
// Create Server instance
var server = net.createServer(onClientConnected); 
 
server.listen(PORT, HOST, function() { 
  console.log('server listening on %j', server.address());
});
 
function onClientConnected(sock) { 
  var remoteAddress = sock.remoteAddress + ':' + sock.remotePort;
  console.log('new client connected: %s', remoteAddress);
 
  sock.on('data', function(data) {
    console.log('%s Says: %s', remoteAddress, data);
    sock.write(data);
    sock.write(' exit');
  });
  sock.on('close'function () {
    console.log('connection from %s closed', remoteAddress);
  });
  sock.on('error', function (err) {
    console.log('Connection %s error: %s', remoteAddress, err.message);
  });
};

TCP Client:

var net = require('net');
 
var HOST = 'localhost';
var PORT = 1234;
 
var client = new net.Socket();
 
client.connect(PORT, HOST, function() {
    console.log('Client connected to: ' + HOST + ':' + PORT);
    // Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
    client.write('Hello World!');
 
});
 
client.on('data', function(data) {   
    console.log('Client received: ' + data);
     if (data.toString().endsWith('exit')) {
       client.destroy();
    }
});
 
// Add a 'close' event handler for the client socket
client.on('close', function() {
    console.log('Client closed');
});
 
client.on('error', function(err) {
    console.error(err);
});

Output:

Server:

D:\node>node server.js server listening on {"address":"127.0.0.1","family":"IPv4","port":1234} new client connected: 127.0.0.1:62682 127.0.0.1:62682 Says: Hello World! connection from 127.0.0.1:62682 closed

Client:

D:\node>node client.js Client connected to: localhost:1234 Client received: Hello World! Client received:  exit Client closed

 

TCP Server:

Here is an example of TCP server in Node.js:

var net = require('net');
 
// Configuration parameters
var HOST = 'localhost';
var PORT = 1234;
 
// Create Server instance
var server = net.createServer(onClientConnected); 
 
server.listen(PORT, HOST, function() { 
  console.log('server listening on %j', server.address());
});
 
function onClientConnected(sock) { 
  var remoteAddress = sock.remoteAddress + ':' + sock.remotePort;
  console.log('new client connected: %s', remoteAddress);
 
  sock.on('data', function(data) {
    console.log('%s Says: %s', remoteAddress, data);
    sock.write(data);
    sock.write(' exit');
  });
  sock.on('close'function () {
    console.log('connection from %s closed', remoteAddress);
  });
  sock.on('error', function (err) {
    console.log('Connection %s error: %s', remoteAddress, err.message);
  });
};

TCP Client:

var net = require('net');
 
var HOST = 'localhost';
var PORT = 1234;
 
var client = new net.Socket();
 
client.connect(PORT, HOST, function() {
    console.log('Client connected to: ' + HOST + ':' + PORT);
    // Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
    client.write('Hello World!');
 
});
 
client.on('data', function(data) {   
    console.log('Client received: ' + data);
     if (data.toString().endsWith('exit')) {
       client.destroy();
    }
});
 
// Add a 'close' event handler for the client socket
client.on('close', function() {
    console.log('Client closed');
});
 
client.on('error', function(err) {
    console.error(err);
});

Output:

Server:

D:\node>node server.js server listening on {"address":"127.0.0.1","family":"IPv4","port":1234} new client connected: 127.0.0.1:62682 127.0.0.1:62682 Says: Hello World! connection from 127.0.0.1:62682 closed

Client:

D:\node>node client.js Client connected to: localhost:1234 Client received: Hello World! Client received:  exit Client closed

ES6 Way:

Let’s update the code in ES6 way. It is assumed you are familiar with following ES6 features:
Class
Arrow Functions
Template literals

TCP Server:

'use strict';
 
// load the Node.js TCP library
const net = require('net');
const PORT = 1234;
const HOST = 'localhost';
 
class Server {
 constructor(port, address) {
  this.port = port || PORT;
  this.address = address || HOST;
  
  this.init();
 }
 
 init() {
  let server = this;
 
  let onClientConnected = (sock) => {
 
   let clientName = `${sock.remoteAddress}:${sock.remotePort}`;
   console.log(`new client connected: ${clientName}`);
 
   sock.on('data', (data) => {
    console.log(`${clientName} Says: ${data}`);
    sock.write(data);
    sock.write('exit');
   });
 
   sock.on('close', () => {
    console.log(`connection from ${clientName} closed`);
   });
 
   sock.on('error', (err) => {
    console.log(`Connection ${clientName} error: ${err.message}`);
   });
  }
 
  server.connection = net.createServer(onClientConnected);
 
  server.connection.listen(PORT, HOST, function() {
   console.log(`Server started at: ${HOST}:${PORT}`);
  });
 }
}
module.exports = Server;

To test server, use following code in another file and run it

const Server = require('./server');
new Server();


TCP Client:

'use strict';
 
const net = require('net');
const PORT = 1234;
const HOST = 'localhost';
 
class Client {
 constructor(port, address) {
  this.socket = new net.Socket();
  this.address = address || HOST;
  this.port = port || PORT;
  this.init();
 }
 init() {
  var client = this;
 
  client.socket.connect(client.port, client.address, () => {
   console.log(`Client connected to: ${client.address} :  ${client.port}`);
   client.socket.write('Hello World!');
  });
 
  client.socket.on('data', (data) => {
   console.log(`Client received: ${data}`);
   if (data.toString().endsWith('exit')) {
    client.socket.destroy();
   }
  });
 
  client.socket.on('close', () => {
   console.log('Client closed');
  });
 
  client.socket.on('error', (err) => {
   console.error(err);
  });
 
 }
}
module.exports = Client;

To test client, use following code in another file and run it

const Client =require('./client');
new Client();

Output:

Server:

D:\node>node serverTest.js Server started at: localhost:1234 new client connected: 127.0.0.1:62846 127.0.0.1:62846 Says: Hello World! connection from 127.0.0.1:62846 closed

Client:

D:\node>node clientTest.js Client connected to: localhost :  1234 Client received: Hello World! Client received: exit Client closed

Promisify the Client:

In your Node application, you might need to trigger server on a particular event like on button click and you want to get ES6 Promise object for neat implementation.

See Also: JavaScript Promises: Understanding Error Handling with Example

Let’s create a method to write socket on client side and returns Promise object.

'use strict';
 
const net = require('net');
const PORT = 1234;
const HOST = 'localhost';
 
class Client {
 constructor(port, address) {
  this.socket = new net.Socket();
  this.address = address || HOST;
  this.port = port || PORT;
  this.init();
 }
 
 init() {
  var client = this;
  client.socket.connect(client.port, client.address, () => {
   console.log(`Client connected to: ${client.address} :  ${client.port}`);
  });
 
  client.socket.on('close', () => {
   console.log('Client closed');
  });
 }
 
 sendMessage(message) {
  var client = this;
  return new Promise((resolve, reject) => {
 
   client.socket.write(message);
 
   client.socket.on('data', (data) => {
    resolve(data);
    if (data.toString().endsWith('exit')) {
     client.socket.destroy();
    }
   });
 
   client.socket.on('error', (err) => {
    reject(err);
   });
 
  });
 }
}
module.exports = Client;

sendMessage method returns Promise object. Let’s see an example how to use it:

const Client =require('./client');
const client = new Client();
client.sendMessage('A')
.then((data)=> { console.log(`Received: ${data}`);  return client.sendMessage('B');} )
.then((data)=> { console.log(`Received: ${data}`);  return client.sendMessage('C');} )
.then((data)=> { console.log(`Received: ${data}`);  return client.sendMessage('exit');} )
.catch((err) =>{ console.error(err); })

To test, remove following line in Server code

sock.write('exit');

Now exit is done by our code.

Output:

Server:

D:\node>node serverTest.js Server started at: localhost:1234 new client connected: 127.0.0.1:63007 127.0.0.1:63007 Says: A 127.0.0.1:63007 Says: B 127.0.0.1:63007 Says: C 127.0.0.1:63007 Says: exit connection from 127.0.0.1:63007 closed


Client:

D:\node>node clientTest.js Client connected to: localhost :  1234 Received: A Received: B Received: C Client closed

Conclusion:

This post has an example of TCP server and client in traditional javascript and ES6 way. Also, an example of promisifying TCP client for better architecture.

Enjoy Node.js and ES6 !!

 

 

 

=================================

=================================

=================================

 

 

 

 

출처: https://m.blog.naver.com/PostView.nhn?blogId=pisgo&logNo=220913542449&categoryNo=0&proxyReferer=&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

 

 

node.js 를 하면서,


C++ 과의 통신이 필요해져서.. 간단하게! 만들어보게 되었습니다 ㅎㅎ


간단한 예제를 만들기 위해,


C++ TCP Server는 MSDN에 있는 소스 코드를 거의 그대로 사용하였습니다 ^^


https://msdn.microsoft.com/en-us/library/windows/desktop/ms737593(v=vs.85).aspx


구조체를 보내는 것을 통신하기 위해 위의 소스에서 구조체 하나를 선언하고,


struct CTestData {
 char a;
 int b;
 char c[15];
};


main 에서 값을 넣어주고, CTestData temp = {'a', 6, "testdata"};


보내는 부분만 수정하였습니다.. iSendResult = send(ClientSocket, (char*)&temp, sizeof(temp), 0);


js 는 클라이언트 부분 코드는 다음과 같습니다..


var net=require('net');
var client = new net.Socket();


var chara = new Buffer(4);
var intb = new Buffer(4);
var charc = new Buffer(16);


client.connect(5555, '127.0.0.1');
client.write('message test');


client.on('data', function(data) {
 //console.log('got data: ', data.toString('utf-8')); 
 chara = data.slice(0, 4);
 intb = data.slice(4, 8);
 charc = data.slice(8, 24);
 console.log('char a :', chara.toString('utf-8'));
 console.log('int b :', intb.readUInt8());
 console.log('char c :', charc.toString('utf-8'));
 client.destroy();
});


client.on('close', function() {
 console.log('closed..');
});


Buffer 에 데이터를 받아오는데, 저 부분을 잘라주는 작업을 거쳤습니다 :)


이 때, char형은 원래 1byte 지만.. padding 3byte를 포함해 전송되는 것에 유의해야 합니다 !
(Memory alignment / Pack 부분에 대한 공부를 하면, 이해하기 좋습니다 ㅎㅎ)


C++ 서버를 실행시켜놓고,


node.js 를 실행시키면 구조체 값을 잘 받아오는 것을 확인할 수 있습니다 ^^

 

 

 

 

=================================

=================================

=================================

 

 

 

 

출처: https://mylko72.gitbooks.io/node-js/content/chapter8/chapter8_3.html

 

 

TCP 소켓 클라이언트 구현

아래와 같이 net.connect()를 호출해 소켓 클라이언트를 생성한다. 연결할 port와 host를 전달하고, 연결 이벤트를 처리할 콜백 함수도 구현한다.

net.connect({port: 8107, host: 'localhost'}, function(){  }); 

콜백 함수 내에서 연결 속성을 설정한다. 아래와 같이 타임아웃이나 인코딩 설정을 할 수 있다.

this.setTimeout(500); this.setEncoding('utf8'); 

data 이벤트를 처리해 서버로부터 받은 데이터를 읽어오려면, 다음 핸들러를 추가한다.

this.on('data', function(data){     console.log("Read from server: " + data.toString());     ...     this.end(); }); 

서버에 데이터를 쓰려면 write() 명령을 실행한다. 서버에 많은 데이터를 쓰거나 쓰기가 실패한 경우, drain이벤트 핸들러를 구현해 버퍼가 비어있을 경우 다시 쓰기를 수행한다.

다음은 쓰기 실패시 처리를 위한 drain 핸들러를 구현하는 예제다. 클로저를 사용해 함수가 종료되더라도 소켓과 데이터 값들을 보존한다.

function writeData(socket, data)
{     
	var success = !socket.write(data);     
    
    if(!success){
    	(function(socket, data){ 
        	socket.once('drain', function(){writeData(socket, data);});})
            (socket, data) 
    }
 }

다음은 기본 TCP 소켓 클라이언트의 전체 구현을 보여준다. 서버에 3개의 다른 소켓이 열려있고 동시에 통신을 하고 있다. 각 클라이언트는 서로 다른 랜덤 포트 번호를 받아 생성된다.

var net = require('net'); 

function getConnection(connName){   
	var client = net.connect({port: 8107, host:'localhost'}, 
    
    function() {     console.log(connName + ' Connected: ');     
    			     console.log('   local = %s:%s', this.localAddress, this.localPort);     
                     console.log('   remote = %s:%s', this.remoteAddress, this.remotePort);
                     this.setTimeout(500);     
                     this.setEncoding('utf8');     
                     this.on('data', function(data) {       
                     	console.log(connName + " From Server: " + data.toString());       
                        this.end();});     
                     
                     this.on('end', function() {       
                     		console.log(connName + ' Client disconnected');});     
                     
                     this.on('error', function(err) {       
                     		console.log('Socket Error: ', JSON.stringify(err));     });     
                         
                     this.on('timeout', function() { console.log('Socket Timed Out'); });     
                     
                     this.on('close', function() { console.log('Socket Closed'); }); 
                     });   
                     
                     return client; 
                } 
                
    function writeData(socket, data){   
    		var success = !socket.write(data);   
            
            if (!success){(
            	function(socket, data){
                	socket.once('drain', function(){ writeData(socket, data);});})(socket, data);} 
                } 
                    
                var Dwarves = getConnection("Dwarves"); 
                var Elves = getConnection("Elves"); 
                var Hobbits = getConnection("Hobbits"); 
                
                writeData(Dwarves, "More Axes"); 
                writeData(Elves, "More Arrows"); 
                writeData(Hobbits, "More Pipe Weed");

TCP 소켓 서버 구현

소켓 서버는 Server 객체의 close 와 error 이벤트와 클라이언트 Socket 객체의 연결 이벤트를 처리해야 한다.

Server 객체를 사용해 소켓 서버를 구현하는 첫 단계는 아래와 같이 net.createServer() 호출을 통해 소켓 서버를 생성한다. 연결 콜백 핸들러를 제공하고 listen() 호출을 통해 포트 수신을 시작한다.

var server = net.createServer(function(client){     ... }); server.listen(8107, function(){     ... }); 

listen 콜백 핸들러 안에서 서버 객체의 close와 error 이벤트를 지원할 핸들러를 추가한다.

server.on('close', function(){     console.log('Server Terminated'); }); server.on('error', function(err){     ... }); 

connection 이벤트 호출 내에서는 연결 속성을 설정한다. 아래와 같이 타임아웃이나 인코딩 설정을 할 수 있다.

this.setTimeout(500); this.setEncoding('utf8'); 

data 이벤트 핸들러를 사용해 클라이언트에서 받은 데이터를 읽어오려면, 다음 핸들러를 추가한다.

this.on('data', function(data){     console.log("Reeived from client: " + data.toString());     ... }); 

다음은 기본 TCP 소켓 서버의 전체 구현을 보여준다. 소켓 서버는 8107 포트로 연결을 받고, 데이터를 읽은 후 클라이언트에 문자열을 쓴다.

var net = require('net'); 
var server = net.createServer(function(client) {   
		console.log('Client connection: ');   
        console.log('   local = %s:%s', client.localAddress, client.localPort);   
        console.log('   remote = %s:%s', client.remoteAddress, client.remotePort);   
        client.setTimeout(500);   
        client.setEncoding('utf8');   
        
        client.on('data', function(data) { console.log('Received data from client on port %d: %s',    
        									client.remotePort, data.toString());     
                                            console.log('  Bytes received: ' + client.bytesRead); 
                                            writeData(client, 'Sending: ' + data.toString());   
                                            console.log('  Bytes sent: ' + client.bytesWritten); });   
                                            client.on('end', function() {    
                                            		console.log('Client disconnected');     
                                                    server.getConnections(function(err, count){       
                                                    	console.log('Remaining Connections: ' + count);  });
                                                        });   
                                                    
                                                    client.on('error', function(err) {     
                                                    	console.log('Socket Error: ', JSON.stringify(err)); }); 
                                                        client.on('timeout', function() {   
                                                        	console.log('Socket Timed out');  
                                                     }); 
                                                     }); 
                                                     
                                                     server.listen(8107, function() {   
                                                     		console.log('Server listening: ' + JSON.stringify(server.address()));  
                                                            server.on('close', function(){     console.log('Server Terminated');   });   
                                                            server.on('error', function(err){     console.log('Server Error: ', JSON.stringify(err));   
                                                            });
                                                            }); 
                                                       
                                                    function writeData(socket, data){ 
                                                    	var success = !socket.write(data);   
                                                        
                                                        if (!success){ (function(socket, data){       
                                                              socket.once('drain', function(){         
                                                                   writeData(socket, data);       
                                                                 });     
                                                                 })(socket, data);   
                                                        } 
                        }

 

 

=================================

=================================

=================================

 

 

 

출처: http://ohgyun.com/370

 

지난 주말엔 회사에서 주최하는 해커톤(hackathon) 행사에 참석했었다.
 
이번엔 모바일 브라우저에서 PC 브라우저의 마우스를 컨트롤 할 수 있는 리모트 컨트롤러를 만들었다.
 
컨트롤러는 트위터 부트스트랩과 Raphael.js로 꾸미고, require.js로 모듈화했고,
통신은 웹소켓으로 하고, 소켓 서버는 node.js를 사용했다.
 

작업한 코드는 github에 넣어뒀다.

https://github.com/ohgyun/remote-controller

 
여기까지 작업하는데 대략 10시간 정도 걸린 것 같다. 비몽사몽이라 기억이.. @_@
 
여튼, 작업 중간중간 메모해둔 게 있어 옮겨둔다.



해결책:

 

node.js 웹소켓 서버
 
 
웹서버 프레임워크는 express를 쓴다.
 
 
express 사용법
 
 
WebSocket과 Socket.io의 차이점
 
 
통신 방법을 websocket으로만 제한하고 싶다면.
     transports 옵션을 webscoket으로만 넣는다.
 
 
socket.io.js 파일 어디에 있나?
     express 3.x 버전에서 socket.io를 사용했기 때문.
     
     3.x에 맞게 바꾸고,
     express의 app.listen()이 아니라, http 서버의 server.listen() 이다.
 
 
socket.io로 방(채널) 만들기
 
 
방 여러개 쓰기 튜토리얼
 
 
__dirname 과 상대경로 ./ 의 차이
 
 
require.js로 부트스트랩이 로드되지 않을 때
 
 
require.js로 raphael이 로드되지 않을 때
 

 

 

=================================

=================================

=================================

 

 

 

 

*기타관련링크

 

http://niceman.tistory.com/109 //html5 websocket 예제

 

- https://techbrij.com/node-js-tcp-server-client-promisify  //ES6 버전으로 서버, 클라이언트 구현

 

https://www.a-mean-blog.com/ko/blog/%EB%8B%A8%ED%8E%B8%EA%B0%95%EC%A2%8C/_/Node-JS-Socket-io-%EC%B1%84%ED%8C%85%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

http://chaeyoungdo.tistory.com/22

 

https://www.slideshare.net/hiscale/111217

 

http://namik.tistory.com/114

 

https://gist.github.com/tedmiston/5935757

 

http://ourcstory.tistory.com/67

 

https://blog.outsider.ne.kr/542

 

http://bcho.tistory.com/896

 

https://dololak.tistory.com/128

 

https://www.zerocho.com/category/NodeJS/post/57df854f5f0b02001505fef2

 

https://skout90.github.io/2017/08/15/Node.js/3.%20%EC%86%8C%EC%BC%93%ED%86%B5%EC%8B%A0/

 

https://okdevtv.com/kr/socket.io-chat-kr.html

 

https://poiemaweb.com/nodejs-socketio

 

https://code.i-harness.com/ko-kr/q/61d33e

 

https://nesoy.github.io/articles/2017-04/Nodejs-Network

 

http://egloos.zum.com/rucaus/v/2495639 

 

https://stackoverflow.com/questions/7340475/client-side-tcp-with-node-js-socket-io

 

 

=================================

=================================

=================================

 

 

 

반응형


관련글 더보기

댓글 영역