用Java建立你第一個區塊鏈-part3
在上一章節中最後說到了要實現p2p網路,那麼在這一章節中就主要說一下p2p網路,實現的方式是什麼,以及為什麼要實現p2p網路。
首先先簡單的介紹一下什麼是p2p網路?p2p網路技術又稱為對等網路技術,是一種網路的新技術,依賴網路中參與者的計算能力和頻寬,而不是把依賴都聚集在較少的幾臺伺服器上。舉個比特幣網路中的例子,之所以能夠在比特幣網路中實現資料的去中心化以及不可篡改,除了依賴於區塊鏈技術,更因為其內在的激勵機制。現在比特幣的價格大家都是有目共睹的,但是如何保證這個價格,所有的挖礦者都認為整個比特幣網路可能被攻擊者給惡意攻擊,所以它們必須提供自己的算力,來不斷保證鏈上的資料是最長的且沒有經過篡改。
做過後臺管理系統的同學們都知道,給一個企業做後臺管理系統,都需要部署其tomcat、資料庫等等,將其部署在自己的私有機器或者阿里雲上,大多數企業都非常重視其資料,所以一般對於生產資料都是需要其相應管理許可權的人員才可以檢視,這就導致了下面的幾個問題。
1、資料的不透明:只針對於內部員工展現資料。
2、資料的不聯通:不同企業之間的資料無法關聯,如果需要關聯必須通過介面進行定製化的開發。
3、資料的不共享:每個企業的資料都只在自己的伺服器上,無法通過大資料分析統計出整個行業的趨勢。
而在區塊鏈中最重要的特性就是去中心化、不可篡改、可追蹤。針對上述問題的解決方案為:
1、資料加密儲存:核心資料只有具備許可權的相關人員才能夠檢視,在鏈上的資料只包括走向,而不包含其核心資料。
2、資料溯源:在鏈上記錄下所有資料,打通資料孤島,產生一個可追蹤的資料交易平臺。
3、資料鏈:適合多方參與、資訊互動的場景,將分散的資料庫連線起來,又可以保護其參與各方的隱私。
所以為了實現資料確權,打通資料孤島,讓所有分佈在各個節點上的資料因為其業務處理關係而聯絡在一起,我採用了socket方式,讓所有節點之間的資料可以進行通訊。
先簡單的介紹兩種socket程式設計
一、一個服務端和一個客戶端之間的通訊
SocketServer類
public class SocketServer {
public static void main(String[] args) {
try {
/** 建立ServerSocket*/
// 建立一個ServerSocket在埠2013監聽客戶請求
ServerSocket serverSocket =new ServerSocket(2013);
while (true) {
// 偵聽並接受到此Socket的連線,請求到來則產生一個Socket物件,並繼續執行
Socket socket = serverSocket.accept();
/** 獲取客戶端傳來的資訊 */
// 由Socket物件得到輸入流,並構造相應的BufferedReader物件
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 獲取從客戶端讀入的字串
String result = bufferedReader.readLine();
System.out.println("Client say : " + result);
/** 傳送服務端準備傳輸的 */
// 由Socket物件得到輸出流,並構造PrintWriter物件
PrintWriter printWriter =new PrintWriter(socket.getOutputStream());
printWriter.print("hello Client, I am Server!");
printWriter.flush();
/** 關閉Socket*/
printWriter.close();
bufferedReader.close();
socket.close();
}
}catch (Exception e) {
System.out.println("Exception:" + e);
}finally{
// serverSocket.close();
}
}
}
SocketClient類
public class SocketClient {
public static void main(String[] args) {
try {
/** 建立Socket*/
// 建立一個流套接字並將其連線到指定 IP 地址的指定埠號(本處是本機)
Socket socket =new Socket("127.0.0.1",2013);
// 60s超時
socket.setSoTimeout(60000);
/** 傳送客戶端準備傳輸的資訊 */
// 由Socket物件得到輸出流,並構造PrintWriter物件
PrintWriter printWriter =new PrintWriter(socket.getOutputStream(),true);
// 將輸入讀入的字串輸出到Server
BufferedReader sysBuff =new BufferedReader(new InputStreamReader(System.in));
printWriter.println(sysBuff.readLine());
// 重新整理輸出流,使Server馬上收到該字串
printWriter.flush();
/** 用於獲取服務端傳輸來的資訊 */
// 由Socket物件得到輸入流,並構造相應的BufferedReader物件
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 輸入讀入一字串
String result = bufferedReader.readLine();
System.out.println("Server say : " + result);
/** 關閉Socket*/
printWriter.close();
bufferedReader.close();
socket.close();
}catch (Exception e) {
System.out.println("Exception:" + e);
}
}
}
二、一個服務端和多個客戶端之間的通訊
Server類 啟用多個執行緒來接受客服端資訊
public class Server extends ServerSocket {
privatestaticfinalintSERVER_PORT =2013;
public Server()throws IOException {
super(SERVER_PORT);
try {
while (true) {
Socket socket = accept();
new CreateServerThread(socket);//當有請求時,啟一個執行緒處理
}
}catch (IOException e) {
}finally {
close();
}
}
//執行緒類
class CreateServerThread extends Thread {
private Socket client;
private BufferedReader bufferedReader;
private PrintWriter printWriter;
public CreateServerThread(Socket s)throws IOException {
client = s;
bufferedReader =new BufferedReader(new InputStreamReader(client.getInputStream()));
printWriter =new PrintWriter(client.getOutputStream(),true);
System.out.println("Client(" + getName() +") come in...");
start();
}
public void run() {
try {
String line = bufferedReader.readLine();
while (!line.equals("bye")) {
printWriter.println("1continue, Client(" + getName() +")!");
line = bufferedReader.readLine();
System.out.println("1Client(" + getName() +") say: " + line);
}
printWriter.println("bye, Client(" + getName() +")!");
System.out.println("Client(" + getName() +") exit!");
printWriter.close();
bufferedReader.close();
client.close();
}catch (IOException e) {
}
}
}
public static void main(String[] args)throws IOException {
new Server();
}
}
SocketClient類
public class SocketClient {
public static void main(String[] args) {
try {
Socket socket =new Socket("127.0.0.1",2013);
socket.setSoTimeout(60000);
PrintWriter printWriter =new PrintWriter(socket.getOutputStream(),true);
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream()));
String result ="";
while(result.indexOf("bye") == -1){
BufferedReader sysBuff =new BufferedReader(new InputStreamReader(System.in));
printWriter.println(sysBuff.readLine());
printWriter.flush();
result = bufferedReader.readLine();
System.out.println("2Server say : " + result);
}
printWriter.close();
bufferedReader.close();
socket.close();
}catch (Exception e) {
System.out.println("Exception:" + e);
}
}
}
因為涉及到專案中的資料,所以我這裡不能夠把一些核心的程式碼給公佈出來,但是核心的邏輯,就是通過服務端與客服端之間的一些訊息的通訊,讓所有資料資訊導儲存在一個鏈條上。