화이트 아날로그 프로그래밍 간단한 비트 코인 시스템, 손의 파도와 쓰기에 당신을 데려 갈! (코드)

저자 | VV 미소ヽ 

Zebian | 캐롤

제작 | 블록 체인베이스 캠프 (blockchain_camp)

커버 | CSDN는 시각적 인 중국을 다운로드 지불

가있는 경우 P2P 의 D 이모, 우리는 어떻게 그들을 블록 체인에 적용 할 수 있는가?

함께 오늘보고 시도!

첫째, 네트워크 내의 복수의 노드를 시뮬레이션 서로 통신 할 필요가, 우리는 본 상황 AB 아래에 도시 된 공정에 걸쳐 두 개의 노드를 가지고 있다고 가정 :

빗질 과정

특히의 전 과정, 무엇을하자 일종의 P2P의 네트워크가 필요로 일을 수행 할 수 있습니다.

  1. 시작 노드 A. A는 처음 생성 블록을 만들

  2. 지갑 A1을 만듭니다. 노드는 지갑에서 제공하는 API 호출을 생성 한 다음 A1 구체 통화는 0입니다.

  3. A1 마이닝. 광산 API가 제공하는 노드로의 호출은 새로운 블록뿐만 아니라 공 보상 시스템과 A1 동전 지갑을 생성한다.

  4. 노드 B를 시작 노드 B의에 동기화 정보 , 현재 블록 체인, 현재 거래 수영장, 현재의 모든 공공 지갑입니다.

  5. 지갑 B1, A2 만들기, API를 노드 A와 B를 호출 (각 노드에 통지) (공개) 중 지갑을 만드는 방송 될 필요가 B, A2 지갑을 말할 수 있도록, 두 개의 노드 만이있다. B 필요는 A, B1 지갑을 알 수 있습니다.

  6. A1이 B1에 전송한다. 제공하는 API A를 호출하는 동안 방송 트랜잭션 .

  7. A2 마이닝 회계. API A가 제공하는 전화뿐만 아니라 방송 새로운 세대의 블록 .

요약하면, 노드는 블록 사슬 네트워크의 시작에 첨가하고, 다른 노드가 동기화 될 필요

  • 블록 사슬 정보

  • 지갑 정보

  • 거래 정보

네트워크의 노드를 가지고, 필요가 다음과 같은 경우에 네트워크의 다른 노드를 통지합니다

  • 새로운 거래

  • 새로운 지갑 만들기

  • 새로운 광산 블록

P2P 일반 프로세스는 다음 몇 가지를 들어, 우리는이 프로세스의 실현 뒤에 결합합니다.

  1. 클라이언트 → 서버는 메시지, 일반적으로 요청 데이터를 전송;

  2. 서버가 메시지를 수신 한 후, 클라이언트 (통화 서비스, 리턴 데이터 처리)에 메시지를 보낸다;

  3. 클라이언트가 수신 된 메시지 처리 용 데이터 (전화 서비스, 데이터 처리).

관련 코드

구현에서, 메시지의 여러 종류 있기 때문에, 메시지를 송신하기 위해 사용되는 메시지 오브젝트를 캡슐화하고, 메시지 유형이 인코딩되어 단일, 메시지 메시지 오브젝트 구현 직렬화 인터페이스, 오브젝트 직렬화 될 수 있도록한다 :

public class Message implements Serializable {
/**
     * 消息内容,就是我们的区块链、交易池等所需要的信息,使用JSON.toString转化到的json字符串
     */
private String data;
/**
     * 消息类型
     */
private int type;
}

메시지 유형에 관련 (유형)입니다 :

/**
 * 查询最新的区块
 */
private final static int QUERY_LATEST_BLOCK = 0;
/**
 * 查询整个区块链
 */
private final static int QUERY_BLOCK_CHAIN = 1;
/**
 * 查询交易集合
 */
private final static int QUERY_TRANSACTION = 2;
/**
 * 查询已打包的交易集合
 */
private final static int QUERY_PACKED_TRANSACTION = 3;
/**
 * 查询钱包集合
 */
private final static int QUERY_WALLET = 4;
/**
 * 返回区块集合
 */
private final static int RESPONSE_BLOCK_CHAIN = 5;
/**
 * 返回交易集合
 */
private final static int RESPONSE_TRANSACTION = 6;
/**
 * 返回已打包交易集合
 */
private final static int RESPONSE_PACKED_TRANSACTION = 7;
/**
 * 返回钱包集合
 */
private final static int RESPONSE_WALLET = 8;

너무 많은 코드 때문에, 모든 위의와 함께, 예를 들어, 다른 노드 지갑 클라이언트 정보를 동기화하기 위해, 여기 붙어 P2P 세 단계 네트워크 상호 작용, 관련 실현 다음 소개합니다.

1, 서버 → 클라이언트가 메시지를 전송 요청 데이터는 일반적으로

먼저 시작 노드 클래스 클라이언트 클라이언트 객체의 생성, 연결 서버, 클라이언트 내부 메소드를 호출.

Main 메서드 시작 클래스 키 코드 (인수가 포트 매개 변수에 배치) :

P2PClient p2PClient = new P2PClient();
String url = "ws://localhost:"+args[0]+"/test";       
p2PClient.connectToPeer(url);

P2PClientconnectToPeer방법 :

public void connectToPeer(String url) throws IOException, DeploymentException {
    WebSocketContainer container = ContainerProvider.getWebSocketContainer();
    URI uri = URI.create(url);
this.session = container.connectToServer(P2PClient.class, uri);
}

P2PClientWebSocketContainer.connectToServer시간이 콜백 것입니다 onOpen우리가 만 공개 정보 조회 지갑을 가정, 기능, 서버는 해당 요청을 받게됩니다.

@OnOpen
public void onOpen(Session session) {
this.session = session;
    p2PService.sendMsg(session, p2PService.queryWalletMsg());
}

참고 : 서비스 용도의 서버 및 클라이언트에 쉽게 통합에 작업 패키지 관련 I 구문 분석 메시지. 해당 부여 queryWalletMsg방법 :

public String queryWalletMsg() {
return JSON.toJSONString(new Message(QUERY_WALLET));
}

물론 앞서 언급 한만큼 sendMsg방법 :

@Override
public void sendMsg(Session session, String msg) {
session.getAsyncRemote().sendText(msg);
}

2의 S erver 메시지를 수신하는 클라이언트로 메시지를 송신 한 후 ( 콜 S의 비 스, 반품 처리 된 데이터 )

서버는 메시지 수신 , 입력 방법을P2PServerOnMessage

/**
 * 收到客户端发来消息
 * @param msg  消息对象
 */
@OnMessage
public void onMessage(Session session, String msg) {
    p2PService.handleMessage(session, msg);
}

p2PService.handleMessage그것은 메시지 (메시지)를 우리가 오는 정보 코드 클라이언트를 수신 한 통화의 다른 유형의 다른 방법 (여기에 거대한 스위치 문이 작은 부분을 소개)에 따라 수신 분석이다 QUERY_WALLET.

@Override
public void handleMessage(Session session, String msg) {
    Message message = JSON.parseObject(msg, Message.class);
switch (message.getType()){
case QUERY_WALLET:
            sendMsg(session, responseWallets());
break;
case RESPONSE_WALLET:
            handleWalletResponse(message.getData());
break;
            ......
    }

정보 코드는 인 QUERY_WALLET호출  responseWallets()방법, 데이터를 얻었다 .

private String responseWallets() {
String wallets = blockService.findAllWallets();
return JSON.toJSONString(new Message(RESPONSE_WALLET, wallets));
}

여기에 나는 또한 서비스, 주어진 다음 캡슐화 관련 작업의 블록 체인을 넣어 findAllWallets지갑의 컬렉션을 통과, 사실, 구체적인 실현, 공공 통계 지갑, 어려움이 없다.

@Override
public String findAllWallets() {
    List<Wallet> wallets = new ArrayList<>();
    myWalletMap.forEach((address, wallet) ->{
        wallets.add(Wallet.builder().publicKey(wallet.getPublicKey()).build());
    });
    otherWalletMap.forEach((address, wallet) ->{
        wallets.add(wallet);
    });
return JSON.toJSONString(wallets);
}

클라이언트에 데이터 및 수익을 얻은 후 :

우리 그래서  responseWallets()접근 방식, 마지막 문장은 메시지 객체를 생성하고 정보 코드를 설정 RESPONSE_WALLET에서 handleMessage호출 된 sendmsg클라이언트에 대한 방법 다시.

case QUERY_WALLET:
        sendMsg(session, responseWallets());
        break;

. (3) C 담보권 T가 (통화 서비스, 데이터 처리) 메시지 데이터를 수신

클라이언트 요청으로 얻은 데이터를받은 방법 :P2PClientOnMessage

@OnMessage
public void onMessage(String msg) {
    p2PService.handleMessage(this.session, msg);
}

또한 우리의 상술 된 입력 p2PService.handleMessage방법이 때 정보 코드를 수신 RESPONSE_WALLEThandleWalletResponse있어서

case RESPONSE_WALLET:
        handleWalletResponse(message.getData());
        break;

handleWalletResponse구현 공개 키 지갑에 수신 된 정보를 분석하고, 클라이언트 노드에 저장 blockService하여.

private void handleWalletResponse(String msg) {
    List<Wallet> wallets = "\"[]\"".equals(msg)?new ArrayList<>():JSON.parseArray(msg, Wallet.class);
    wallets.forEach(wallet -> {
        blockService.addOtherWallet(walletService.getWalletAddress(wallet.getPublicKey()),wallet );
    });
}

때문에 주입 서비스의 사용은 @Autowired 서버 (@ServerEndpoint) 및 클라이언트 (@ClientEndpoint)에 사용 주석이 콩을 주입하는 방법과 구체적인 구현은, 때문에 싱글 봄 부팅을 제공합니다.

널 포인터 예외가 발생합니다 서비스를 사용하는 경우 그리고 새로운 객체를 생성 웹 소켓마다, 그래서, 그러므로, 우리는 봄 같은 도구 틸 때마다 서비스를 필요로 만들어 우리에게 봄 컨테이너에서 사용할 수있다 콩 원하는 도구 클래스 코드는 아래와 같습니다.

public class SpringUtil implements ApplicationContextAware {
public static ApplicationContext applicationContext;
    @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext != null) {
            SpringUtil.applicationContext = applicationContext;
        }
    }
/**
     * 获取applicationContext
     */
public static ApplicationContext getApplicationContext() {
return applicationContext;
    }

/**
     * 通过name获取 Bean.
     */
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
    }
/**
     * 通过class获取Bean.
     */
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
    }

/**
     * 通过name,以及Clazz返回指定的Bean
     */
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
    }
}

테스트가 전에 우리가 설정해야합니다 그래서 SpringUtil되어 applicationContext클래스의 시작 아래에 주어진 구성과 관련 노드 (간단한 테스트를 위해, 클래스 두 개의 노드가 다른 인수의 처리에 따라, 각각 부팅을 공유).

public static void main(String[] args) {
    System.out.println("Hello world");
    SpringUtil.applicationContext  = SpringApplication.run(Hello.class, args);
if (args.length>0){
        P2PClient p2PClient = new P2PClient();
        String url = "ws://localhost:"+args[0]+"/test";
try {
            p2PClient.connectToPeer(url);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

사용에서, 우리는 수동으로 콩을 얻을 필요가 :

//之前是这样//@Autowired//private P2PService p2PService;//改正后,去掉Autowired,每次使用都手动获取beanprivate P2PService p2PService;@OnOpenpublic void onOpen(Session session) {//如果不使用那些,在这里会报空指针异常,p2PService 为 null p2PService = SpringUtil.getBean(P2PService.class);//新增这句话从IVO容器中获取bean p2PService.sendMsg(session, p2PService.queryWalletMsg());}

안녕하세요 노드, 서버로 테스트 때 :

테스트 노드, 클라이언트로 테스트 할 때.

이것은, 우리는 서버와 클라이언트 노드의 상호 작용 P2P 네트워크 노드를 실현. 나는 당신이 시도 할 수 있습니다 제안하고 우리는 코멘트 영역과 오 논의!

추천 도서 

☞는 헤어 아웃이 없습니다! 떨림 + 다트 신속하게 아름다운 모바일 앱을 구축으로

내가 좋은 일을 뭘 찾았 게? 자바 옵션, 확실히 가치가 학습 | 포스 프로그램

2020 CVPR | 텐센트가 ACNet 언급의 세분화 된 분류를 결합, 효과는 최신 SOTA까지입니다

내가 좋아하는 클라우드 IDE 추천!

고급 지능의 견고 서면 계약을 갖추고 있습니다

반환 E 직원이 작업 추가 정보로 돌아갑니다 : 다시 일을, 무한, 허페이 (合肥) 되돌아 가서 다음, 첫째 날과 회사에 의해 전세 선택

당신은 내가 즐겨 찾기로 심각하게, 모든 점에서 보면

출시 1830 원저 · 원 찬양 40000 + · 조회수 16,540,000을 +

추천

출처blog.csdn.net/csdnnews/article/details/104890435