首页

Java实现简单区块链(成语接龙)

java

2020-6-30

Java实现区块链,成语接龙实例。

Java

package tech.topcoder.blockchain;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
 * 区块链实现
 *
 */
public class BlockChain {
    public static List<Block> blockchain = new ArrayList<>();

    static final String ipPrev = "192.168.8."; // 对局域网内的电脑进行扫描,找到最长的链,下载到本地

    static final String dataFileDir = "c://blockchain"; // 本地存储路径

    /**
     * 创建新块
     */
    public static Block newBlock(int index, String proof, String hash, Timestamp t, String sender, String recipient) {
        Block block = null;

        block = new Block(index, proof, hash, t, sender, recipient);

        return block;
    }

    public static void init() {
        System.out.println("===>初始化...");
        File dirFile = new File(dataFileDir);
        if (!dirFile.exists()) {
            dirFile.mkdir();
            // 往新创建的本地文件里面写一个创世块
            try {
                FileOutputStream fos = new FileOutputStream(dirFile   "//data.txt");
                fos.write((BlockChain.createFirstBlock().toInfoString()   "\r\n").getBytes("UTF-8"));
                fos.close();
            } catch (Exception e) {
            }
        }
    }

    /**
     * Hash一个块
     */
    public static String hash(Block block) {
        String hash = null;

        String s = block.previousHash   block.proof   block.recipient   block.sender   block.createTime.toString();
        hash = MD5(s);

        return hash;
    }

    /**
     * 创始块的创建,创世块是一个块,必须是固定的信息
     * 
     * 逻辑上来说,只有在区块链产品的第一个用户第一次启动的时候,才会需要创建创世块
     */
    public static Block createFirstBlock() {
        try {
            Timestamp t = new Timestamp(
                    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2018-01-01 01:01:01").getTime());
            return newBlock(0, "海阔天空", "*", t, "*", "*");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String MD5(String key) {
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        try {
            byte[] btInput = key.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            java.security.MessageDigest mdInst = java.security.MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i  ) {
                byte byte0 = md[i];
                str[k  ] = hexDigits[byte0 >>> 4 & 0xf];
                str[k  ] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 验证当前的成语是否符合规则
     * 
     * @param prev
     *            前一个成语
     * @param current
     *            当前成语
     */
    public static boolean validProof(String prev, String current) {
        // 验证这个成语的头一个字是不是上一个成语的最后一个字
        if (current.charAt(0) != prev.charAt(prev.length() - 1)) {
            return false;
        }
        try {
            String content = httpRequest(
                    "http://chengyu.t086.com/chaxun.php?q="   URLEncoder.encode(current, "gb2312")   "&t=ChengYu",
                    5000, "gbk");
            if (content == null || content.indexOf("没有找到与您搜索相关的成语") != -1 || content.indexOf("搜索词太长") != -1) {
                return false;
            } else {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static String httpRequest(String urlAddr, int connectTimeout) {
        return httpRequest(urlAddr, connectTimeout, null);
    }

    public static String httpRequest(String urlAddr, int connectTimeout, String charset) {
        InputStream iStream = null;
        try {
            URL url = new URL(urlAddr);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            if (connectTimeout > 0) {
                connection.setConnectTimeout(connectTimeout);
            }
            if (connection.getResponseCode() == 200) {
                iStream = connection.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buf = new byte[1024];
                int len = 0;
                while ((len = iStream.read(buf)) != -1) {
                    baos.write(buf, 0, len);
                    baos.flush();
                }

                if (charset != null) {
                    return baos.toString(charset);
                } else {
                    return baos.toString("UTF-8");
                }
            }
        } catch (Exception e) {
        } finally {
            if (iStream != null) {
                try {
                    iStream.close();
                } catch (Exception ex) {
                }
            }
        }
        return null;
    }

    /**
     * 从网络读取区块链数据到本地文件
     */
    public static void downloadData() {
        File dirFile = new File(dataFileDir);
        if (!dirFile.exists()) {
            dirFile.mkdir();
            // 往新创建的本地文件里面写一个创世块
            try {
                FileOutputStream fos = new FileOutputStream(dirFile   "//data.txt");
                fos.write((BlockChain.createFirstBlock().toInfoString()   "\r\n").getBytes("UTF-8"));
                fos.close();
            } catch (Exception e) {
            }
        }

        // 扫描周边的节点,找到最长的链,下载到本地
        int lastLen = 0;
        String lastChain = "";
        for (int i = 0; i < 255; i  ) {
            String url = "http://"   ipPrev   i   ":8080/blockchain/chain.jsp";
            System.out.println(url);
            String chain = httpRequest(url, 10);
            if (chain != null && chain.length() > 0) {
                chain = chain.trim();
                System.out.println(chain);
                String[] temp = StringUtils.splitByWholeSeparator(chain, "##");
                if (temp.length > lastLen) {
                    lastLen = temp.length;
                    lastChain = chain;
                }
            }
        }

        try {
            if (lastChain != "") {
                FileOutputStream fos = new FileOutputStream(dirFile   "//data.txt");
                fos.write((lastChain.replace("##", "\r\n")   "\r\n").getBytes("UTF-8"));
                fos.close();
            }
        } catch (Exception e) {
        }
    }

    public static String stringBlockChain() {
        try {
            FileInputStream fis = new FileInputStream(new File(dataFileDir   "//data.txt"));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = fis.read(buf)) != -1) {
                baos.write(buf, 0, len);
                baos.flush();
            }
            fis.close();

            String chain = baos.toString("UTF-8");
            return StringUtils.join(chain.split("\r\n"), "##");
        } catch (Exception e) {
            return "";
        }
    }

    public static void loadData() {
        String chain = stringBlockChain();
        String[] chains = StringUtils.splitByWholeSeparator(chain, "##");
        blockchain.clear();
        for (String s : chains) {
            String[] temp = StringUtils.split(s, "#");
            String[] time = StringUtils.split(temp[3], ".");
            Timestamp t = new Timestamp(DateUtil.parse(time[0]).getTime());
            Block block = newBlock(Integer.valueOf(temp[0]), temp[1], temp[2], t, temp[4], temp[5]);
            blockchain.add(block);
        }
    }

    public static void writeData() {
        try {
            List<String> chains = new ArrayList<>();
            for (Block block : blockchain) {
                chains.add(block.toInfoString());
            }
            FileOutputStream fos = new FileOutputStream(dataFileDir   "//data.txt");
            fos.write((StringUtils.join(chains, "\r\n")   "\r\n").getBytes("UTF-8"));
            fos.close();
        } catch (Exception e) {
        }
    }
}

资源下载此资源下载价格为3D币(VIP免费),请先
资源文件列表
BlockChain/.classpath , 1276
BlockChain/.project , 1086
BlockChain/.settings/.jsdtscope , 639
BlockChain/.settings/org.eclipse.core.resources.prefs , 162
BlockChain/.settings/org.eclipse.jdt.core.prefs , 430
BlockChain/.settings/org.eclipse.ltk.core.refactoring.prefs , 106
BlockChain/.settings/org.eclipse.m2e.core.prefs , 90
BlockChain/.settings/org.eclipse.m2e.wtp.prefs , 86
BlockChain/.settings/org.eclipse.wst.common.component , 597
BlockChain/.settings/org.eclipse.wst.common.project.facet.core.xml , 292
BlockChain/.settings/org.eclipse.wst.jsdt.ui.superType.container , 49
BlockChain/.settings/org.eclipse.wst.jsdt.ui.superType.name , 6
BlockChain/.settings/org.eclipse.wst.validation.prefs , 50
BlockChain/.settings/org.eclipse.wst.ws.service.policy.prefs , 87
BlockChain/pom.xml , 1617
BlockChain/src/main/java/tech/topcoder/blockchain/Block.java , 2615
BlockChain/src/main/java/tech/topcoder/blockchain/BlockChain.java , 9382
BlockChain/src/main/java/tech/topcoder/blockchain/DateUtil.java , 24868
BlockChain/src/main/java/tech/topcoder/blockchain/InitListener.java , 406
BlockChain/src/main/webapp/answer.jsp , 1517
BlockChain/src/main/webapp/chain.jsp , 309
BlockChain/src/main/webapp/detail.jsp , 1822
BlockChain/src/main/webapp/index.jsp , 1502
BlockChain/src/main/webapp/js/jquery-1.10.2.js , 93113
BlockChain/src/main/webapp/login.jsp , 614
BlockChain/src/main/webapp/sync.jsp , 566
BlockChain/src/main/webapp/WEB-INF/web.xml , 757
BlockChain/target/classes/tech/topcoder/blockchain/Block.class , 2749
BlockChain/target/classes/tech/topcoder/blockchain/BlockChain.class , 8925
BlockChain/target/classes/tech/topcoder/blockchain/DateUtil.class , 12757
BlockChain/target/classes/tech/topcoder/blockchain/InitListener.class , 679
BlockChain/target/m2e-wtp/web-resources/META-INF/MANIFEST.MF , 105
BlockChain/target/m2e-wtp/web-resources/META-INF/maven/tech.topcoder/blockchain/pom.properties , 239
BlockChain/target/m2e-wtp/web-resources/META-INF/maven/tech.topcoder/blockchain/pom.xml , 1617
没有账号? 忘记密码?

社交账号快速登录