Blockchain> rpc통신을 http통신으로 전환하기

YU YU·2021년 9월 27일
0

경일_BlockChain

목록 보기
13/24
post-thumbnail

목표
http통신으로 코인을 거래한다.
1. http로 요청을 보낸다.
2. Node.js환경에서 테스트를 한다.
3. express를 이용서 요청을 보내고 받는다.

curl을 통해서 데몬을 실행시켜서 http에 요청을 보낸다.
curl은 쉘명령여서 리눅스 환경에서만 사용가능하다.

01. curl [option][도메인]

curl은 쉘스크립트 명령어여서 리눅스에서만 사용 가능하다.

curl의 형태

  • H: header
  • d: data
  • X: request method
  • ex) crul -X POST -H "" -d "data~" http://naver.com

rpc통신에는 유저와 패스워드 들어가야 한다.
rpcuser:rpcpaswword@ipaddress:rpcport
위 형태가 주소값이다. 도메인과 같은 값이라고 보면 된다.

아래의 정보로 통신을 해보자.

rpcuser=penguin
rpcpassword=1234
ipaddress=127.0.0.1
rpcport=3001

그러면 도메인은 penguin:1234@127.0.0.1:3001이 된다. 이를 crul에 적용하면 아래의 코드와 같이 된다.

curl -X POST -H "" -d "data~" penguin:1234@127.0.0.1:3001
rpc통신은 json형식이기에 헤더부분을 고치면 이렇게 된다.
curl -X POST -H "Content-type: application/json" -d "{}" penguin:1234@127.0.0.1:3000
data부분에 명령어와 params를 쓸 수 있다.

{
	"method":"getnewaddress",
    	"params":["penguine1"]
}

params값은 여러개 올 수도 있어서 배열로 처리한다.

즉, 완성된 명령어는 아래오 같다.
curl -X POST -H "Content-type: application/json" -d '{ "method":"getnewaddress","params":["penguine1"] }' penguin:1234@127.0.0.1:3001
이를 리눅스에 입력하면 다음과 같이 나온다. (꼭! 리눅스 환경에서 입력해야 한다)

02. Node.js를 통해 브라우저로 결과 보여주기.

  1. node.js구축
  2. express구축
  3. express에서 http요청을 보낼 수 있게 한다.

2-1.node.js환경 구축

  1. 윈도우에서 server.js 파일을 만든다.
  2. npm init 으로 node.js환경을 만든다.
  3. npm i express로 express를 구축한다.
  4. npm i request로 request 라이브러리를 구축한다.

    목적
    우리가 여태까지 했던 터미널이나 wsl 작업들을 http통신을 이용해서 한다. 즉, 코인의 갯수를 알아보거나하는 명령어들을 리눅스나 터미널이 아닌 http통신으로 가능하게 한다.

    이렇게 하면 데몬이 돌아가고, server.js를 돌리는 코드도 돌아가야 하니 서버가 최소 2대가 돌아감을 알 수 있다.
    전체적인 요청과 응답을 보면 다음과 같다.

다음과 같은 코드를 만들어준다.

//server.js
const express= require('expres');
const port = 3800;
const app = express();

app.get('/',(req,res)=>{
    res.send('hello pencoin')
})

app.listen(port,()=>{
    console.log(`server port ${port}`)
})

위의 코드는 제대로 express가 작동하는지 확인해보는 코드이다.ㅣ


잘 작동함을 알 수 있다.

2-2.request()

request메소드는 요청 속의 요청이 가능하게끔 하는 함수이다. 아래와 같은 작업이 가능하게끔 한다.

형태
request(url,callback)
2개의 인자값이 존재한다.

  • 첫번째 인잣값은 정보를 어디로 보낼지 명시하는 값이다.
    url(string) or object{url}
  • 두번째 인잣값은 callback함수이다.
    이 콜백함수는 (err,response,data)세개의 인자값을 받는다.
    - response : 결과를 객체로 반환한다.
    - data : 결과를 string으로 출력해준다.

네이버 정보 요청하기

A요청 B
A요청은 uri로 /naver를 요청하는 것이고,
B요청은 http://naver.com의 내용을 요청하는 것이다. 즉, 네이버의 body영역을 가져오는 요청이다.

const express= require('express');
const port = 3800;
const app = express();
const request=require('request')
//기본적으로 함수

app.get('/',(req,res)=>{
    res.send('hello pencoin')
})

app.get('/naver',(req,res)=>{
    request(`https://naver.com`,(err,response,body)=>{
        console.log(body);
    });  
    res.send('naver');
})

app.listen(port,()=>{
    console.log(`server port ${port}`)
})

위와 같이 입력하고 터미널에node server.js를 입력해 서버를 실행시키고 브라우저에 127.0.0.1:3800을 입력하면 다음과 같이 나온다.

브라우저엔 res.send('naver')이 출력되고,

터미널엔 console.log(body)가 출력이 된다. 엄청 길다

console.log(body)console.log(response)로 바꾸면 json형식으로 나온다.

err를 입력하고 주소를 https://naver.cm으로 잘못 입력해보자.



브라우저에선 res.send(naver)를 제대로 출력해준다. 터미널창에서는 connect오류가 뜬다. 우리가 원하는대로 A요청>B요청>B응답>A응답 이런 식으로 처리되지 않고, A요청>B요청>A응답>B응답 이런 식으로 실행이 된 것이다. 이를 비동기로 만들기위해서는 단순히 async await로 처리하자고 생각할 수도 있다. 그러나 async await는 결과가 promise 객체로 떨어져야지만 가능한 것이다. request 함수는 callback으로 처리하기때문에 promise객체로 떨어지는게 아니어서 async await를 이용해 비동기처리를 할 수 없다.

아래와같이 res.send('naver) 구문의 위치를 바꿔주면 B라는 응답을 주고, A의 응답을 받는 순서가 된다.

const express= require('express');
const port = 3800;
const app = express();
const request=require('request')
//기본적으로 함수

app.get('/',(req,res)=>{
    res.send('hello pencoin')
})

app.get('/naver',(req,res)=>{
    //request함수는 2개의 인자값 존재
    //1.어디로 정보를 보낼지 url(string) or object{url}
    //2.callback(3개의 인자값) 
    request(`https://naver.cm`,(err,response,body)=>{
        // 응답을 객체형태로 가져오는게 response
        //         string형태로 가져오는게 body
        console.log(err);
      	res.send('naver');
    });
    
    
})
...


오류 메세지가 달라진 걸 확인할 수 있다.

예제2 (예외처리)

...
app.get('/naver',(req,res)=>{
    request(`https://naver.cm`,(err,response,body)=>{
        console.log(err);
        msg = "naver"
        if(err==null){
            res.send(msg);
        }else{
            res.send(err);
        }
      res.send('naver');
    });    
})
...

위와 같이 출력됨을 알 수 있다.

예제3(첫번째 인잣값에 객체로 url넣기)

app.get('/naver2',(req,res)=>{
    request({url:"http://never.com"},(err,response,data)=>{
        console.log(data)
        res.send('naver2')
    })
})

{}로 보내는데는 이유가 있다. 여러정보를 보낸다는 것이다.

예제4(첫번째 인잣값에 여러가지 정보를 넣기)

app.get('/naver2',(req,res)=>{
    request({
        url:"http://never.com",
        method:"POST",
        headers:{"Content-type":"application/json"},
        body:"{msg:'hello world!'}"
        },
        (err,response,data)=>{
        console.log(data)
        res.send('naver2')
    })
})

크롤링
html의 body영역에서 자동으로 해당 영역의 data영역을 빼오는 것이다.
npm i cheerio cheerio 패키지를 깐다.
cheerio는 text를 읽어서 element 상태로 변환시켜 저장하는 역할을 한다.

app.get('/crawling',(req,res)=>{
    request(`https://naver.com`,(err,response,data)=>{
        let $ = cheerio.load(data); //선택자 return 값은 함수임
        $('.partner_box_wrap > .partner_box:nth-child(3) > a').each((index,item)=>{
            console.log(item.children[0].data)
            let {data} = item.children[0]
            console.log(data);
            //selector
        })
    })
    res.send('ggg')
})

예제 5

http로 새로운 지갑 주소 생성하기

계정명을 uri로 받아서 새로운 지갑주소를 생성하는 코드를 만들어보자.

app.get('/newaddress/:account',(req,res)=>{
    const {account} = req.params
    headers={"Content-type": "application/json"};
    body=`{"method":"getnewaddress","params":["${account}"]}`;

    const USER=process.env.RPC_USER || 'penguin';
    const PASS = process.env.RPC_PASSWORD || '1234';
    const RPCPORT= process.env.RPC_PORT || 3001;
    const options={
        url:`http://${USER}:${PASS}@127.0.0.1:${RPCPORT}`,
        method:"POST",
        headers,
        body
    }

    const callback = (err,response,data)=>{
        if(err==null && response.statusCode ==200) {
            const body = JSON.parse(data);
            res.send(body)
        }else{
            res.send(err)
        }
    }
    request(options,callback)
})

하면 브라우저에 다음과 같은 주소를 입력하면 결과가 다음과 같이 나올 것이다.

3001번 포트의 penguin3의 지갑주소p6T6RxyDdYg8PpyZuwiXrBVYGLYoUKfnYw가 생성되었다. 이건 새로운 지갑 주소를 생성하는 명령어이므로 할 때마다 새로운 지갑 주소가 생긴다.


윈도우 터미널에서 getaddressesbyaccount API를 이용해 생성된 지갑의 주소들을 알아보자.

위에서 본 주소들이 나옴을 알 수 있다.

profile
코딩 재밌어요!

0개의 댓글