/主節(jié)點(diǎn)廣播后建立字節(jié)點(diǎn)的廣播
package main
import (
"os"
"fmt"
"net/http"
"io"
)
type nodeINfo struct {
// 節(jié)點(diǎn)名稱(chēng)
id string
//節(jié)點(diǎn)路徑
path string
// http 相應(yīng)
write http.ResponseWriter
}
// 創(chuàng)建map老翘,存儲(chǔ)各個(gè)國(guó)家的ip地址
var nodeTable = make(map[string]string)
func main() {
// 接收終端參數(shù)
userId := os.Args[1]
fmt.Println(userId)
// 存儲(chǔ)四個(gè)國(guó)家的ip地址
nodeTable = map[string]string{
"Apple" :"localhost:1111",
"MS" :"localhost:1112",
"Google" :"localhost:1113",
"IBM" :"localhost:1114",
}
// 創(chuàng)建國(guó)家對(duì)象
node := nodeINfo{id:userId,path:nodeTable[userId]}
// http協(xié)議的回掉函數(shù)
// http://localhost:1111/req?warTime =1111
http.HandleFunc("/req",node.request)
http.HandleFunc("/prePrepare",node.prePrepare)
http.HandleFunc("/prepare",node.prepare)
http.HandleFunc("/commit",node.commit)
if err:=http.ListenAndServe(node.path,nil);err!=nil {
fmt.Println(err)
}
}
// http服務(wù)器区赵,接收到網(wǎng)絡(luò)請(qǐng)求并且映之。req則回掉request
func (node *nodeINfo)request(writer http.ResponseWriter,request *http.Request) {
// 該命令允許request請(qǐng)求參數(shù)
request.ParseForm()
if (len(request.Form["warTime"])>0) {
node.write =writer
fmt.Println("主節(jié)點(diǎn)接收到的參數(shù)信息為",request.Form["warTime"][0])
// 激活主節(jié)點(diǎn)后向其他的節(jié)點(diǎn)發(fā)送廣播
node.broadcast(request.Form["warTime"][0],"/prePrepare")
}
}
// 節(jié)點(diǎn)發(fā)送廣播的方法
func (node *nodeINfo)broadcast(msg string,path string) {
fmt.Println("廣播",path)
// 遍歷所有的節(jié)點(diǎn)
for nodeId,url :=range nodeTable {
if nodeId== node.id{
continue
}
// 使當(dāng)前節(jié)點(diǎn)外的節(jié)點(diǎn)作出相應(yīng)
http.Get("http://"+url+path+"?warTime="+msg+"&nodeId="+node.id)
}
}
//處理廣播后接收到的數(shù)據(jù)
func (node *nodeINfo)prePrepare(writer http.ResponseWriter,request *http.Request) {
request.ParseForm()
fmt.Println("接收到的廣播為",request.Form["warTime"][0])
if len(request.Form["warTime"])>0 {
node.broadcast(request.Form["warTime"][0],"/prepare")
}
}
//接收子節(jié)點(diǎn)的廣播
func (node *nodeINfo)prepare(writer http.ResponseWriter,request *http.Request){
request.ParseForm()
//打印
fmt.Println("接收到子節(jié)點(diǎn)的廣播",request.Form["warTime"][0])
//校驗(yàn)
if len(request.Form["warTime"])>0 {
node.authentication(request)
}
}
var authenticationNOdeMap =make(map[string]string)
var authenticationSuceess =false
// 校驗(yàn)拜占庭
func (node *nodeINfo)authentication(request *http.Request ) {
if !authenticationSuceess {
if len(request.Form["nodeId"])>0 {
authenticationNOdeMap[request.Form["nodeId"][0]]="OK"
// 如果由兩個(gè)國(guó)家節(jié)點(diǎn)成功正確返回了結(jié)果便锨,則成功
if len(authenticationNOdeMap)>len(nodeTable)/3 {
authenticationSuceess = true
node.broadcast(request.Form["warTime"][0],"/commit")
}
}
}
}
// 返回成功相應(yīng)
func(node *nodeINfo)commit(writer http.ResponseWriter,request *http.Request) {
if writer !=nil {
fmt.Println("拜占庭校驗(yàn)成功哈哈哈哈哈哈哈")
io.WriteString(node.write,"ok")
}
}
/*運(yùn)行起來(lái)主節(jié)點(diǎn)歪架,一次運(yùn)行子節(jié)點(diǎn),然后運(yùn)行網(wǎng)頁(yè)端的http://localhost:1111/req?warTime=1111
然后看圖
*/葛闷,
主節(jié)點(diǎn)廣播的圖:
image.png
字節(jié)點(diǎn)1:
image.png
字節(jié)點(diǎn)2:
[圖片上傳中...(image.png-5b30e8-1527060651051-0)]
字節(jié)點(diǎn)3
image.png
這樣一個(gè)字節(jié)點(diǎn)的廣播服務(wù)算是成功了