기본 콘텐츠로 건너뛰기

WEB-RTC 개발 - 1 (WEB-RTC with Nodejs)

WEB-RTC 개발 - 1 (WEB-RTC with Nodejs)

이번시간에 구성해 볼 기능은 첫번째 단계인 사용자가 접속하여 웹 클라이언트 페이지를 받는 단순한 HTTP 서버와,

서로의 신호를 주고받을 수 있는 시그널링 역할을 하는 웹소캣 서버를 만들어 볼 예정이다.

개발 언어로는 Nodejs를 활용할 예정이다.

구현할 기능의 단계는 크게 아래 3가지로 구분되어 진다.

1. http 서버를 구현하여 사용자가 접속하면 화상채팅을 할 수 있는 페이지를 전달하여 준다.

2. 서로가 같은 네트워크에 붙어있음을 확인할 수 있는 시그널링 역할을 하는 웹소캣 서버를 만든다.

3. 서로의 시그널링을 주고받을 수 있도록 웹 페이지에서 웹소캣 서버로 접속을 하는 기능을 만든다.

첫 번째 단계를 위해서 http 모듈을 설치한다.

npm install http

모듈이 설치되고 난 이후에 일반 요청에 대해서 간단한 페이지를 보여주도록 작업한다.

작성할 파일 명칭은 index.js로 하였다.

const http = require('http'); const fs = require('fs'); const port = 3000; //포트 const pathName = './html/index.html'; const server = http.createServer(function(request, response) { //일반 HTTP 요청 처리 fs.readFile(pathName, function (err, data) { if (err) { response.writeHead(404, { 'Content-Type': 'text/html' }); } else { response.writeHead(200, { 'Content-Type': 'text/html' }); response.write(data.toString()); } response.end(); }); }); server.listen(port, function() { console.log((new Date()) + ' Server is listening on port 3000'); });

전혀 어렵지 않는 코드이다. 3000번으로 접속요청이 들어온 경우 html폴더의 index.html 파일을 사용자에게 전달 하도록 하였다.

index.html 파일의 내용은 일단 간단하게 hello world라는 텍스트가 보여지게 하였다.

webrtc Hello world

접속을 하면 정상적으로 Hello world화면이 보여진다.

여기까지가 사용자에게 웹 페이지를 전달하는 기능이다.

해당 기능까지가 웹페이지를 사용자에게 전달하는 내용이다.

다음단계로 사용자가 서로 신호를 주고받을 수 있도록 웹소켓 서버를 작성한다.

웹소켓 모듈을 설치 한다.

npm install websocket

* 웹 소켓 관련 글 주소

https://ko.wikipedia.org/wiki/%EC%9B%B9%EC%86%8C%EC%BC%93

서버코드인 index.js를 1차 수정 한다.

//맨 위의 코드 내용 생략 ----- const WebSocketServer = require('websocket').server; const wsServer = new WebSocketServer({ httpServer: server, //기존에 만든 http서버를 활용 autoAcceptConnections: false //true인경우 서버가 허용하지 않는 기타 요청도 가능해짐 });

위 4줄의 코드 내용이 어렵지는 않다. 내용 그대로 웹 소켓 서버를 기존 구현된 http 서버를 활용해서 구동시키는 내용이다.

다음으로 사용자의 요청에 대해서 신호를 지속적으로 유지하도록 하는 기능을 추가하여보자.

const rooms = new Map(); //커넥션을 담을 객체 wsServer.on('request', function(request) { //응답을 받는다. const user = request.resourceURL.query.user; //사용자 ID var connection = request.accept(); //들어온 커넥션 객체 rooms.set(user,{con:connection}); //커넥션 추가 connection.on('message', function(message) { //서로의 메시징이 도달하면 for(let target of rooms.entries()) { //전달 if (message.type === 'utf8') { console.log('Received : ' + message.utf8Data); target[1].con.sendUTF(message.utf8Data); } else if (message.type === 'binary') { console.log('Received Binary'); target[1].con.sendBytes(message.binaryData); } } }); connection.on('close', function(reasonCode, description) { //커넥션이 끊기면 rooms.delete(user); //삭제 }); });

사용자의 개별 커넥션을 담기 위해서 Map 객체를 사용 하였다. Map 객체에 들어온 요청에 대해서 고유의 키 값을 활용하여 커넥션을 담아 두었다.

"사용자 ID"라는 부분은 고유의 키 값처럼 사용할 내용이며, 사용자가 요청할 때(index.html) 전달하도록 만들 예정이다.

각각의 브라우저가 해당 키 값을 통해서 Map객체에 저장되도록 하기 위해서 이다.

중간에 connection 객체의 on함수에 message로 되어있는 부분이 서로의 메시징이 주고받을 때 하는 행동을 기록한 내용 이다.

* 참고사항 : 무조건 2명이서만 사용하는 기능으로 구현되어 있다. 나중에 map 부분의 기능을 수정하면 채팅방과 같은 기능도 가능 하다.

1차로 완성된 일반 웹 + 시그널링 서버(index.js)이다.

const http = require('http'); const fs = require('fs'); const port = 3000; //포트 const pathName = './html/index.html'; const server = http.createServer(function(request, response) { //일반 HTTP 요청 처리 fs.readFile(pathName, function (err, data) { if (err) { response.writeHead(404, { 'Content-Type': 'text/html' }); } else { response.writeHead(200, { 'Content-Type': 'text/html' }); response.write(data.toString()); } response.end(); }); }); server.listen(port, function() { console.log((new Date()) + ' Server is listening on port 3000'); }); //signal server area ------------------------------------------------------------------------------- const WebSocketServer = require('websocket').server; const wsServer = new WebSocketServer({ httpServer: server, //기존에 만든 http서버를 활용 autoAcceptConnections: false //true인경우 서버가 허용하지 않는 기타 요청도 가능해짐 }); const rooms = new Map(); //커넥션을 담을 객체 wsServer.on('request', function(request) { //응답을 받는다. const user = request.resourceURL.query.user; //사용자 ID var connection = request.accept(); //들어온 커넥션 객체 rooms.set(user,{con:connection}); //커넥션 추가 connection.on('message', function(message) { //서로의 메시징이 도달하면 for(let target of rooms.entries()) { //전달 if (message.type === 'utf8') { console.log('Received : ' + message.utf8Data); target[1].con.sendUTF(message.utf8Data); } else if (message.type === 'binary') { console.log('Received Binary'); target[1].con.sendBytes(message.binaryData); } } }); connection.on('close', function(reasonCode, description) { //커넥션이 끊기면 rooms.delete(user); //삭제 }); });

클라이언트(index.html) 페이지에서는 웹 소켓에 대한 연결, 닫힘, 메시징 전달 기능을 1차로 구현해 보도록 하겠다.

그리고 앞서 만든다고 하였던 고유 id값을 전달 해 주는 기능도 작성해 보겠다.

1차로 작성한 웹소캣 접속 코드이다.

var url = 'ws://127.0.0.1:3000?user=고유아이디필요!!'; var socket = new WebSocket(url); socket.onopen =function () { console.log('connection ok'); }; socket.onclose =function () { console.log('connection fail'); }; socket.onmessage = function (response) { var msg = response.data; console.log(msg); };

웹소캣 객체는 웹표준에 의해서 사용되는 객체이므로 어떤 브라우저든지 간에 동일하게 적용이 된다.

코드 자체가 매우 직관적이라 설명을 생략 한다.

해당 코드에 id를 만들어주는 함수와, 테스트용으로 메시지를 보낼 기능을 붙여보았다.

1차로 완성된 클라이언트(index.html)의 모습이다.

Title var url = 'ws://127.0.0.1:3000?user='+makeid(10); var socket = new WebSocket(url); socket.onopen =function () { //접속 console.log('connection ok'); }; socket.onclose =function () { //종료 console.log('connection fail'); }; socket.onmessage = function (response) { //전달 var msg = response.data; console.log(msg); }; $('#clicker').click(function(){ //웹소켓 서버로 메시징 전달 var value = $('#chat').val(); socket.send(value); }); function makeid(length) { //랜덤아이디 만들기 함수 var result = ''; var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var charactersLength = characters.length; for ( var i = 0; i < length; i++ ) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; }

이제 서버를 구동하여 보자. 브라우저 2개를 켠 뒤에 접속하여보자.

서로 전달받은 메시지가 콘솔창에 뜨는 모습 서버에 도착한 메시지 로그

위 내용처럼 이상없이 동작 하였다면 1차구현 목표에 도달 한 것이다.

오늘 작업 한 개념을 간단히 정리하여보자.

위 사진과 같이 각각의 클라이언트가 동일한 웹 주소로 접속하여 웹소켓 서버를 통해서 시그널링(메시지)을 주고받았다.

서로의 메시지가 정확하게 전달 되었으므로 브라우저간의 1차준비는 완료 된 것이다.

다음시간에는 web-rtc를 적용하는 부분에 대해서 알아보도록 하겠다.

web_rtc_.7z 0.00MB

from http://lts0606.tistory.com/223 by ccl(A) rewrite - 2020-03-06 04:54:05

댓글

이 블로그의 인기 게시물

[Mac OS X] 데스크탑 응용프로그램 개발시작

[Mac OS X] 데스크탑 응용프로그램 개발시작 현재 회사에서 다음 프로젝트로 Mac OS X를 개발해야 하는 일정이 생겨 난생 처음 데스크탑 응용프로그램을 개발하기 공부를 시작했고 여러가지 플랫폼이 있다는것을 발견했다. 어떤 플랫폼을 사용해야할 지 먼저 고민해보자. 무엇으로 개발할것인가? Xcode & Swfit or Objective-C Mac OS X 는 objective-c를 기반으로 만들어졌다. apple에서 제공하는 Xcode와 objective-c 혹은 Swift로 응용 프로그램을 만들 수 있다. Electron Electron 프레임워크를 사용하면 javascript, HTML, CSS를 사용하여 크로스 플랫폼 데스크탑 응용 프로그램을 만들 수 있다. react-native-desktop Qt 프레임 워크를 기반으로하는 크로스 플랫폼이다. react-native 와 javascript로 응용 프로그램을 만들 수 있다. Qt는 컴퓨터 프로그래밍에서 GUI 프로그램 개발에 널리 쓰이는 크로스 플랫폼 프레임워크. 각 플랫폼의 장단점은 무엇인가? Xcode & Swfit or Objective-C - 장점 모든 OSX API에 직접 접근할 수 있다. Xcode를 통해 App Store에 쉽게 배포할 수 있다. - 단점 Windows 전용 응용 프로그램을 다시 개발해야한다. Swift언어를 모른다면 새로 공부해야 한다. Electron - 장점 웹스택을 가지고 빠르게 만들 수 있다. 다양한 플랫폼을 지원한다. - 단점 Native언어로 개발할때 보다 성능이 떨어질 이슈가있다. OS X API를 사용하는데 복잡하다. *API에 대한 JavaScript 래퍼가 없으면 자체 래퍼를 작성하지 않는 한 프로젝트에서 사용할 수 없습니다. React-native-desktop - 장점 현재 개발스택과 완전히 동일하므로 더 빠르게 개발 할 수 있다. 다양한 플랫폼을 지원한다. - 단점 N...

AWS CI/CD 파이프라인에 Slack 알람 적용(Lambda, CloudWatch Events 연동)

AWS CI/CD 파이프라인에 Slack 알람 적용(Lambda, CloudWatch Events 연동) 이번 글에서는 구축된 CI/CD 파이프라인과 Slack 알람을 연동하는 방법에 대해서 알아볼 것이다. CI/CD 파이프라인 시작/종료(성공/실패) 시 Amazon CloudWatch Events에서 해당 이벤트를 감지한 후 AWS Lambda로 트리거 신호를 보내면 AWS Lambda에서 Slack채널로 알람을 보내는 프로세스다. 글의 순서는 다음과 같다. Amazon CloudWatch Events, AWS Lambda란? 실습 전 준비사항 Slack Webhook 생성 AWS Lambda 함수 생성 AWS CloudWatch Events 생성 테스트 위와 같은 방식으로 구축을 하면 최종 프로세스는 다음 그림과 같다 (우리가 이 글에서 진행하는 내용은 빨간색으로 표시된 부분) 1. Amazon CloudWatch Events, AWS Lambda란? 1-1. Amazon CloudWatch Events란? Amazon CloudWatch Event(혹은 AWS CloudWatch Events)는 AWS 상태 변경 등을 감시할 수 있는 기능이다. 만약 사용자가 만든 규칙에 맞는 이벤트가 발생하게 되면 해당 이벤트가 사정에 정의된 규칙과 일치할 경우 하나 이상의 대상 작업을 호출한다. 이벤트 유형에 따라 알람을 보내거나, 이벤트 정보를 캡쳐하거나, 교정작업을 수행하거나, 이벤트를 시작하거나, 기타 작업을 수행할 수 있다. 이벤트가 발생할 경우 대상 작업은 AWS Lambda함수, AWS Kinesis 스트림, AWS SQS, Amazon SNS 등이 있다. 사용되는 사례로는 1) 이벤트가 발생하면 Lambda함수를 사용하여 Slack채널로 알림을 전달하거나, 2) AWS 상태 이벤트가 발생하면 Lambda 및 CloudWatch Events를 사용하여 Amazon SNS로 사용자 지정 텍스트 또는 SMS 알림을 보내는 등...

[2020-angstromCTF] web - A peculiar query write-up

[2020-angstromCTF] web - A peculiar query write-up English write-up UI seems like below. If you click the 'the source' link, you can get back-end source code. const express = require("express"); const rateLimit = require("express-rate-limit"); const app = express(); const { Pool, Client } = require("pg"); const port = process.env.PORT || 9090; const path = require("path"); const client = new Client({ user: process.env.DBUSER, host: process.env.DBHOST, database: process.env.DBNAME, password: process.env.DBPASS, port: process.env.DBPORT }); async function query(q) { const ret = await client.query(`SELECT name FROM Criminals WHERE name ILIKE '${q}%';`); return ret; } app.set("view engine", "ejs"); app.use(express.static("public")); app.get("/src", (req, res) => { res.sendFile(path.join(__dirname, "index.js")); }); app.get("/", async (req, res) => { if (req.query...