1) Server - Client Server 구축하기 (Node.js / express)
1) 기본 server 구축
블록체인은 탈중앙화이지만 지금 구축하는 웹서버는 중앙 서버가 존재하는 하이브리드형 블록체인 p2p이다. 웹서버를 구축하는 이유 : 블록 가져오기 / peer / 간단한 기록 / 버전 / 중단 기능을 위함 !
p2p에 대한 자세한 포스팅
https://blckchainetc.tistory.com/333
경로 src 에서 express 설치
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 서버 on => console.log 잘 나오는지 확인
** 윈도우에서의 환경변수 설정
위의 코드에 process.env.[변수명]을 적어서 환경변수를 사용할 수 있다.
환경변수 설정 / 확인 방법 on Windows
set [변수명]=값
set [변수명]
on Mac or Linux
export [변수명]=값
2) blocks.js 가져오기 + app.get '/blocks' 으로 Blocks 가져오기
json으로 대화하므로 ! body-parser 설치 / 가져오기 / 사용하기
npm i body-parser
server.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
app.use(bodyParser.json());
block.js - block.js module 화 하기
module.exports = {
getBlocks, getVersion, addBlock, getLastBlock,
}
server.js blocks 객체로 가져오기 + /blocks app.get 작성
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const bc = require('./block'); // -> 요렇게 변수로 가지고만 와도 server.js실행 시 bc도 실행된다.
app.use(bodyParser.json());
app.get('/blocks', (req,res)=>{
res.send(bc.getBlocks());
})
app.listen(port, ()=>{
console.log(`server start port ${port}`)
})
=> bc 변수로 가져오기만 해도 server.js를 실행시키면 bc (block.js) 도 실행된다.
server on => window terminal Linux에서 응답 확인해보기
curl -X GET http://localhost:3000/blocks
=
curl http://localhost:3000/blocks
* json 형태로 나오도록 하려면 python 설치된 상태에서 아래 명령어 입력
curl -X GET http://localhost:3000/blocks python -m json.tool
< Linux 명령어 >
curl : http 통신 할거야
- : 옵션이 있어
-X : request Method (ex. POST, GET,,,)
-H : Header
-D : Data
* -D data를 보낼 때 ↓↓
-d "{\"data\":[\"Helloooo\"]}" => "{"data":["hello"]}"
쌍따옴표로 감싸는 스트링 안에 쌍따옴표를 쓸 떄는 \" <- 요렇게 적어주기ㅣ
3. Version 확인하기
server.js - app.get('/version') 추가
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const bc = require('./block');
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}`)
})
Comman on Linux
curl -X GET http://localhost:3000/version // or
curl http://localhost:3000/version -X GET
Comman on Window browser
4. 방금 구축한 Client-Server 웹서버에서 '블록' 추가해보기
src > server.js
// 블록 추가하기
app.post('/mineBlock', (req,res)=>{
let {data} = req.body;
const result = bc.addBlock(data);
if(result==false){
res.send('mineBlock(addBlock) failed')
}else{
res.send(result)
}
})
req.body = POST
리눅스에서 명령어를 입력할 때, data를 입력할 예정!
bc(block.js)의 addBlock() 함수 에서 return하는 값이 없으므로 수정
block.js
// 새로운 block을 간단히 추가하는 함수
function addBlock(data){
const newBlock = nextBlock(data);
if(isValidNewBlock(newBlock, getLastBlock()) && isValidBlocks(Blocks)){
Blocks.push(newBlock);
return Blocks;
}
return false;
}
Blocks에 성공적으로 추가가되면 return Blocks 블록이 담긴 배열을 돌려주기
Server off => on 하고 Comman on Linux
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
질문 : 오류가 남 !
Block.js에서
// 새로운 block을 간단히 추가하는 함수
function addBlock(data){
const newBlock = nextBlock(data);
console.log('newBlock=',newBlock)
if(isValidNewBlock(newBlock, getLastBlock())){
// if(isValidNewBlock(newBlock, getLastBlock()) && isValidBlocks(Blocks)){
Blocks.push(newBlock);
return Blocks;
}
return false;
}
isValidBlocks(Blocks) 를 조건에 같이 넣어주었는데 제네시스 블록 비교하는 두 개의 Timestamp가 달라서 false 가 뜨는 것 같다. => 일단 빼주기!
다시 Linux 명령어 -> Data가 "Hello" 라는 블록체인이 추가됨 !
5. 프로세스 종료하기 on Linux
vs terminal에서 Crtl + c 로 서버 끄지않고 Linux 명령으로 끄도록 만들기
server.js 코드 추가
// 서버 끄기
app.get('/stop', (req,res)=>{
res.send(`server's just stopped ! `)
process.exit(0)
})
Command on Linux
curl -X GET http://localhost:3000/stop
or
curl http://localhost:3000/stop
Server - Client 끝!
2) Socket server 만들기 (with ws)
1. ws 기본 세팅
- npm 설치
npm i ws
- src > network.js 파일 생성 + 코드 작성
const WebSocket = require('ws');
const wsPORT = process.env.WS_PORT || 6005;
local server.js PORT = 3000
socket network PORT = 6005
=> 한 컴퓨터에 두 개의 port 열기
2. socket 만들기
const WebSocket = require('ws');
const wsPORT = process.env.WS_PORT || 6005;
// [전역변수 sockets] 소켓에 연결된 사용자(peer)들을 모아놓은 list
let sockets=[];
function getSockets(){
return sockets;
}
// 최초의 접속
function wsInit(){
const server = new WebSocket.Server({port:wsPORT});
server.on('connection', (ws)=>{
console.log('ws=',ws)
init(ws)
})
}
function init(ws){
sockets.push(ws)
}
3. socket.io의 broadcast 기능 구현
* socket.io는 body내용을 객체로 보내고 받는게 가능했다! (사용하기 편리하게 만들어 놓은 것)
* ws는 정석대로, 원래 데이터를 string으로 주고 받음 -> parse해서 객체로 변환해서 사용해야함
network.js
function write(ws,message){
// message 객체를 -> string으로 바꿔서 보냄
ws.send(JSON.stringify(message));
}
function broadcast(message){
sockets.forEach(socket=>{
write(socket,message)
})
}
4. connectionToPeer 함수 생성
function connectionToPeers(newPeers){
// peer -> string주소값 ex) ws://localhost:7001
// ** 주의 ws는 프로토콜! http를 대체함
newPeers.forEach(peer=>{
const ws = new WebSocket(peer)
// WebSocket.Server는 직접 Open까지 해주는데 WebSocket
ws.on('open', ()=>{init(ws)})
// ERROR
ws.on('error',()=>{console.log(`ConnectionToPeers failed`)})
})
}
5. server.js 실행할 때 network.js도 시작되도록 만들기
network.js 모듈화
module.exports={
wsInit, getSockets, broadcast, connectionToPeers,
}
server.js
const ws = require('./network');
.
.
.
ws.wsInit();
app.listen(port, ()=>{
console.log(`server start port ${port}`)
})
=> server off -> on => 오류있는지 점검
=> port 3000, 6005 둘 다 열림 !
network.js 전체 코드
const WebSocket = require('ws');
const wsPORT = process.env.WS_PORT || 6005;
// [전역변수 sockets] 소켓에 연결된 사용자(peer)들을 모아놓은 list
let sockets=[];
function getSockets(){
return sockets;
}
// 최초의 접속
function wsInit(){
const server = new WebSocket.Server({port:wsPORT});
server.on('connection', (ws)=>{
console.log('ws=',ws)
init(ws)
})
}
function write(ws,message){
// message 객체를 -> string으로 바꿔서 보냄
ws.send(JSON.stringify(message));
}
function broadcast(message){
sockets.forEach(socket=>{
write(socket,message)
})
}
function connectionToPeers(newPeers){
// peer -> string주소값 ex) ws://localhost:7001
// ** 주의 ws는 프로토콜! http를 대체함
newPeers.forEach(peer=>{
const ws = new WebSocket(peer)
// WebSocket.Server는 직접 Open까지 해주는데 WebSocket
ws.on('open', ()=>{init(ws)})
// ERROR
ws.on('error',()=>{console.log(`ConnectionToPeers failed`)})
})
}
function init(ws){
console.log(`ws server start port ${wsPORT}`)
sockets.push(ws)
}
module.exports={
wsInit, getSockets, broadcast, connectionToPeers,
}
6. Block 모으기
server.js
app.get('/peers',(req,res)=>{
res.send(ws.getSockets().map(socket=>{
return `${socket._socket.remoteAddress}: ${socket._socket.remotePort}`
}))
})
질문 : pure p2p 는 어떻게 하는건지 !?
'블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기' 카테고리의 다른 글
[121일차] WebSocket ws로 Server 구현 (0) | 2021.09.07 |
---|---|
[120일차] 블록체인 ws WebSocket (0) | 2021.09.06 |
[119일차] 블록체인 네트워크 웹소켓 http ws 웹서버 구축 (0) | 2021.09.03 |
[118일차 복습] 블록체인 새 블록 추가, 연결하고 검증하기 (0) | 2021.09.03 |
[118일차] 블록체인 새 블록 추가, 연결하고 검증하기 (0) | 2021.09.02 |