P2P (Peer to Peer) 구현 방법
-> WebSocket
-> socket.io = 웹소켓으로 웹으로 구성할 때 필수적인 구성을 미리 만들어 놓은 패키지
이전 node.js chatting을 만들 때 사용함
기본 기능 외 여러가지 기능이 많다.
처음 사용하는 사람이 사용하기 편하다
-> ws (web socket 약자)
접속에 대한 것만 ex) broadcast, to
블록체인은 두 개의 port가 필요
1) 서버 - 클라이언트
2) 노드끼리 통신
오늘 웹서버 구축의 기초작업 / setting 예정 !
1) server - client http 서버 먼저 만들기
with express
express 설치 **** 터미널 경로 src 에서
npm i express
src > server.js 파일 생성
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
app.listen(port,()=>{
console.log(`server start port ${port}`)
})
잘 나오는지 확인
node server.js
환경변수 설정
윈도우 - ** "" or '' 따옴표 없음
set [변수명]=값
set [변수명] // 확인
mac or linux
export [변수명]=값
env | grep [변수명]
환경변수 port number 바꿔보기
<웹서버 구축 목적>
블록 가져오기
peer / 간단한 기록들 / 버전
중단
server.js - 어제 만든 blocks 가져오기
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const bc = require('./block.js') //const {getBlocks} require~ 와 같음. 이번엔 객체로 가져와서 쓰기
app.listen(port,()=>{
console.log(`server start port ${port}`)
})
json으로 대화할 예정 ! -> bodyParser 설치 / 가져오기 / 코드 작성
npm i body-parser
server.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser')
const bc = require('./block.js') //const {getBlocks} require~ 와 같음. 이번엔 객체로 가져와서 쓰기
app.use(bodyParser.json());
app.get('/blocks', (req,res)=>{
res.send(bc.getBlocks())
})
app.listen(port,()=>{
console.log(`server start port ${port}`)
})
window terminal에서 아래 명령어 입력해서 응답 쳌
리눅스 명령어임 !리눅스 환경에서 해야해
curl -X GET http://localhost:3000/blocks
curl http://localhost:3000/blocks -X GET (요것도 가능!)
-X 을 써서 method 입력 가능
-X GET
-X POST
python이 설치되어 있다면 아래 명령어로 더 편리하게 볼 수 있다.
curl -X GET http://localhost:3000/blocks | python3 -m json.tool
Python 이 없다면 Postman 사용 가능 !
Version 확인
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const bc = require('./block.js'); //const {getBlocks} require~ 와 같음. 이번엔 객체로 가져와서 쓰기
app.use(bodyParser.json());
app.get('/blocks', (req,res)=>{
res.send(bc.getBlocks());
})
app.get('/version',(req,res)=>{
res.send(bc.getVersion());
})
app.listen(port,()=>{
console.log(`server start port ${port}`);
})
블록을 추가하는 것을 웹 서버에서 해보기
data이다 보니 post로 해보기
src > server.js
app.post('/mineBlock',(req,res)=>{
let {data} = req.body;
const result = bc.addBlock(data) // 응답을 수정해보기
})
src> block.js 응답 보내는 곳 newBlock을 보내도록 수정
// 얘는 단순히 Push만 할 것 ! 인자값에 배열을 넣어주기 (data)
function addBlock(data) {
// new header 만들어서 => new block(header, body)
const newBlock = nextBlock(data) // return 다음 블록에 대한 객체
// newBlock과 마지막
if(isValidNewBlock(newBlock, getLastBlock())){
Blocks.push(newBlock);
return newBlock; //함수가 여기서 끝나버리게 -------------true -> newBlock 수정
}
return false;
}
=> result 는 false or newBlock 둘 중 하나의 응답을 받게됨 !
app.post('/mineBlock',(req,res)=>{
let {data} = req.body;
const result = bc.addBlock(data) // 응답을 수정해보기
if(result ==false){
res.send(`mineBlock failed')`)
}else{
res.send(result)
}
})
리눅스 명령어 설명
// curl - http 통신을 할거다 ~ 라는 의미
// 모든 리눅스 명령어는 - 는 옵션값
// -X : request method (ex. POST, GET,..)
// -H : "Content-Type:application/json" // H : header
// -H 쓰고 header 더 쓸 수 있음
// -d "{\"data\":[\"Helloooooo\"]}" // D : data
POST 리눅스에서 아래 명령어 실행
curl -X POST -H "Content-Type:application/json" -d "{\"data\":[\"hello\"]}" http://localhost:3000/mineblock
or python json tool 사용해서
curl -X POST -H "Content-Type:application/json" -d "{\"data\":[\"hello\"]}" http://localhost:3000/mineblock | python3 -m json.tool
=> 실행할 때마다 index가 늘어남 (new block 이 생성되고 있음 !)
=> 하나의 서버가 블록체인과 통신할 수 있는 server가 생김 !
프로세스 종료하기
vs terminal 에서 Ctrl + c 로 server 끄는 거 말고 원격으로 끄도록 만들기
server.js 코드 추가 -> server 쪽에 코드를 수정 or 추가할 시에는 꼭 server를 껐다가 켜야함 !!!!!!*
app.get('/stop',(req,res)=>{
res.send("server's jsut stopped (●ˇ∀ˇ●)")
process.exit(0)
})
Client server 끝!
이제 socket server만들기
ws를 사용해서 구현해보기
1. npm 설치
npm i ws
2. src > network.js 파일 생성 + 코드작성
const WebSocket = require('ws');
const wsPORT = process.env.WS_PORT || 6005;
터미널 명령어
set WS_PORT=6005
set WS_PORT // 로 확인
하나의 컴퓨터에 두 개의 port를 열어 놓기 !
아까 만든 client server = 3000
지금 만들 ws server = 6005
3. socket 만들기
const WebSocket = require('ws');
const wsPORT = process.env.WS_PORT || 6005;
// 전역변수 sockets - 소켓에 연결된 사람(peer)들을 모아놓은 list
let sockets =[];
function getSockets(){
return sockets
}
// socket은 event 적인 js code가 많아! event 란 ? 보통 비동기 (async await)
// Object.on('msg',()=>{ ()=> .... blabla.........콜백지옼
// 최초의 접속 socket.io 에서 connect와 같은..
function wsInit(){
const server = new WebSocket.Server({port:wsPORT});
// 첫번째 인자값은 msg 값 , 그리고 두 번째 인자값 = 함수를 실행하겠다.
// wsPORT(port 6005)인 server
// 웹소켓의 인자값 ws를 받아 어디론가 전달해줄 것
server.on('connection',(ws)=>{
console.log('ws=',ws)
init(ws)
})
}
function init(ws){
sockets.push(ws)
}
4. socket.io의 broadcast 기능 구현
socket.io는 body내용을 객체로 보내고 받는게 가능
ws는 정석대로, 원래 데이터는 string으로 주고 받는 것 - > parse해서 객체로 변환해서 쓰는 것이었다..
// 최초의 접속 socket.io 에서 connect와 같은..
function wsInit(){
const server = new WebSocket.Server({port:wsPORT});
// 첫번째 인자값은 msg 값 , 그리고 두 번째 인자값 = 함수를 실행하겠다.
// wsPORT(port 6005)인 server
// 웹소켓의 인자값 ws를 받아 어디론가 전달해줄 것
server.on('connection',(ws)=>{
console.log('ws=',ws)
init(ws)
})
}
function write(ws,message){
// message 객체 를 글자로 바꿔서 보내준다.
ws.send(JSON.stringify(message))
}
function init(ws){
sockets.push(ws)
}
5. broadcast
function write(ws,message){
// message 객체 를 글자로 바꿔서 보내준다.
ws.send(JSON.stringify(message))
}
function broadcast(message){
sockets.forEach( socket=>{
// 나 자신에게 msg 보내기
write(socket, message)
})
}
function init(ws){
sockets.push(ws)
}
6. Peer
function connectionToPeers(newPeers){ //newPeers 는 배열
// peer -> string 주소 값 ws://localhost:7001
// http protocal 대신 ws 포로토콜!
newPeers.forEach(peer=>{
// 접속
const ws = new WebSocket(peer) //websocket자체를 실행(도메인넣기) 아까 한 Server는 포트만 넣어 생성한 것
// WebSocket.Server는 open까지 해주는데 WebSocket는 직접 옵흔해주기
ws.on('open',()=>{init(ws)})
// ERROR
ws.on('error',()=>{console.log(`Connection failed (newPeers.forEach ERROR...)`)})
})
}
7. server.js 시작할 때, network.js도 시작되도록 하기
network.js module exports
module.exports = {
wsInit, getSockets, broadcast, connectionToPeers,
}
server.js 가져와서 실행
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const bc = require('./block.js'); //const {getBlocks} require~ 와 같음. 이번엔 객체로 가져와서 쓰기
const ws = require('./network.js');
.
.
.
ws.wsInit();
app.listen(port,()=>{
console.log(`server start port ${port}`);
})
server 실행해보고 오류가 있는지 점검
node server.js
=> 3000번 , 6005번 각각 port가 둘 다 열림
8. Block을 모으기
express : Client
Websocket : server 측의 느낌이 있음....
peers 를 볼 수 있는 것 => 현재 가지고 있는 socketlist (getSockets) -> get
addPeers, peer를 추가하는 것이 필요 -> 내가 보낼 주소 값에 소켓을 생성하는 작업 (connectToPeers) -> 데이터를 넘겨줌 -> post
// peers 현재 가지고 있는 socket List
app.get('/peers',(req,res)=>{
// ws.getSockets() => return 배열
res.send(ws.getSockets().map(socket=>{
return `${socket._socket.remoteAddress}:${socket._socket.remotePort}`;
}))
})
리눅스에 명령어 입력
curl http://localhost:3000/peers
addpeers
// addpeers -> 내가 보낼 주소값에 소켓을 생성하는 작업
// data 보내야하니깐 POST
// curl -X POST -H "Content-Type:application/json" -d "{\"peers\":[\"ws://localhost:7001\", \"ws://localhost:7002\"]}" http://localhost:3000/addPeers
app.post('/addPeers', (req,res)=>{
const peers = req.body.peers || [] // 예외처리
ws.connectionToPeers(peers);
res.send('success');
})
server off - >on ** 반드쉬
curl -X POST -H "Content-Type:application/json" -d "{\"peers\":[\"ws://localhost:7001\", \"ws://localhost:7002\"]}" http://localhost:3000/addPeers
failed 되는 것은 당연한 것이라고 함 !
이유 : ws://localhost:7001 로 실행된 건 없다..
local에 7001이 구동되고 있어야함!
내pc에서 7001을 구동시켜보자
websocket은 client, server 둘 다 될 수 있다.
src 폴더 복사 -> src2 명명
server.js port : 3001
netword.js : 7001로 수정
src node server.js
src2 node server.js 둘 다 실행하기 !
어렵군어려워..
<코드 흐름 이해,,,>
하나의 컴퓨터 안에
1) port 3000 실행 (http 통신규약)
2) port 6005 실행 (ws 웹소켓 통신규약)
=> server.js 로 묶여있음 !
3000, 6005번이 함께 컴퓨터에 돌고 있는 상태
ws -> 모듈로 빼서 server.js 파일이 ws에 접근할 수 있다.
curl -X GET http://3000/peers ~ 요청 on Linux
요청을 받은 http://3000/peers express가 실행
----> ws://6005 getSockets()의 결과물을 반환 to 3000
-----> 3000은 결과를 ----> Linux 로 돌려줌 (test로 받은 것 !)
curl -X POST http://3000/addPeers 요청 on Linux
요청 받은 http://3000/addPeers -> connectionToPeers() (http:6001) 실행 -> ws://7001,7002 이 없는데 -> 실패라고 응답 to 3000 -----> 3000 응답 전달 ---> Linux says failed.
-> src 를 복사해서 3001, 7001 로 수정 => 총 server 4대가 돌아가고 있음 !
http3001은 사실 필요가 없다 ! 근데 ws 7001이 필요! ws7001만 만들면 되는데 빠른 진행위해 그냥 복사해서 넣은 것!
3000/addPeers 를 linux에 구동시킨 수 만큼 peers 배열에 추가가 된다.
오늘 배운건 채팅과 같은 원리 - 그저 터미널로 했을뿐 !
사실 웹소켓에 연결된 것- Clinet & Server의 연결
이번 주말 과제 : 이전에 해본 socket.io 대신 ws 로 채팅 구현해보기
'블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기' 카테고리의 다른 글
[120일차] 블록체인 ws WebSocket (0) | 2021.09.06 |
---|---|
[119일차 복습] 블록체인 네트워크 웹소켓 http ws 웹서버 구축 (0) | 2021.09.06 |
[118일차 복습] 블록체인 새 블록 추가, 연결하고 검증하기 (0) | 2021.09.03 |
[118일차] 블록체인 새 블록 추가, 연결하고 검증하기 (0) | 2021.09.02 |
[117일차 복습] 블록체인 제네시스 블록 만들기 with JavaScript (0) | 2021.09.01 |