【區塊鏈編程01】如何搜索其他節點——多播協議mDNS及Go語言實現服務器和瀏覽器

不知道區塊鏈是如何尋找同服務節點,連入門都不算。更何況之後的零知識證明、身份認證和工作量證明?

下面看看mDNS到底是什麼?

在計算機網絡中 , 多播DNS ( mDNS )協議將主機名解析爲不包含本地名稱服務器的小型網絡中的IP地址。 它是一種零配置服務,使用與單播域名系統 (DNS)基本相同的編程接口,數據包格式和操作語義。 雖然Stuart Cheshire將mDNS設計爲獨立協議,但它可以與標準DNS服務器協同工作。

mDNS協議發佈爲 RFC 6762使用IP多播用戶數據報協議 (UDP)數據包,由Apple Bonjour和開源Avahi軟件包實現。 Android包含mDNS實現。 mDNS也已在Windows 10中實現,最初僅限於發現網絡打印機[3] ,後來也能夠解析主機名。

mDNS可以與DNS服務發現 (DNS-SD)結合使用, DNS服務發現是RFC 6763中單獨指定的配套零配置技術。

網絡中的mDNS是什麼形狀?

mDNS 協議規定了端口爲 5353,而 DNS 的端口是 53。

mDNS 基於 UDP 協議。DNS 一般也是基於 UDP 協議的,但是也可以使用 TCP 協議。

如果理解了 DNS 協議,再去理解 mDNS 協議就很簡單了,區別只是 mDNS 一般作用在一個局域網內的,有特定的 IP 地址,也就是 224.0.0.251,有特定的端口 5353,mDNS 的作用是實現局域網內的服務發現,查詢,註冊,DNS 作用是實現域名的解析,作用大概是一樣的。

Go語言如何實現一個mDNS?

代碼位置:https://github.com/grandcat/zeroconf

在ZeroConf庫的ReadMe文件中,實現了一個簡單的mDNS服務。

服務:


package main

import (
	"github.com/grandcat/zeroconf"
	"log"
	"time"
	"os/signal"
	"os"
	"syscall"
)

func main()  {
//"_workstation._tcp"定義了服務名稱
//參數形式:
//func Register(instance, service, domain string, port int, text []string, ifaces []net.Interface)

	server, err := zeroconf.Register("GoZeroconf", "_workstation._tcp", "local.", 42424, []string{"txtv=0", "lo=1", "la=2"}, nil)
	if err != nil {
	    panic(err)
	}
	defer server.Shutdown()

	// Clean exit.
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
	select {
	case <-sig:
	    // Exit by user
	case <-time.After(time.Second * 120):
	    // Exit by timeout
	}

	log.Println("Shutting down.")
}

瀏覽器:

package main

import (
	"context"
	"github.com/grandcat/zeroconf"
	"log"
	"time"
)

func main()  {
	for  {
		// Discover all services on the network (e.g. _workstation._tcp)
		resolver, err := zeroconf.NewResolver(nil)
		if err != nil {
			log.Fatalln("Failed to initialize resolver:", err.Error())
		}

		entries := make(chan *zeroconf.ServiceEntry)
		go func(results <-chan *zeroconf.ServiceEntry) {
			for entry := range results {
				log.Println(entry)
			}
			log.Println("No more entries.")
		}(entries)

		ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
		defer cancel()
		err = resolver.Browse(ctx, "_workstation._tcp", "local.", entries)
		if err != nil {
			log.Fatalln("Failed to browse:", err.Error())
		}

		<-ctx.Done()
	}
}

服務未開啓時,運行瀏覽器輸出:

2020/04/12 12:38:10 No more entries.

開啓服務(單行輸出):

2020/04/12 12:38:29 &{{GoZeroconf _workstation._tcp local. 
_workstation._tcp.local. GoZeroconf._workstation._tcp.local. 
_services._dns-sd._udp.local.} jiang-P95-HR.local. 42424 
[txtv=0 lo=1 la=2] 3200 [192.168.1.103] 
[fe80::2055:d255:6444:ea00]}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章