真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Bytom怎么實現(xiàn)P2P網(wǎng)絡(luò)upnp端口映射

這篇文章主要介紹“Bytom怎么實現(xiàn)P2P網(wǎng)絡(luò)upnp端口映射”,在日常操作中,相信很多人在Bytom怎么實現(xiàn)P2P網(wǎng)絡(luò)upnp端口映射問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Bytom怎么實現(xiàn)P2P網(wǎng)絡(luò)upnp端口映射”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

創(chuàng)新互聯(lián)是一家專業(yè)提供宿豫企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計、H5響應(yīng)式網(wǎng)站、小程序制作等業(yè)務(wù)。10年已為宿豫眾多企業(yè)、政府機構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進行中。

UPNP介紹

UPNP(Universal Plug and Play)通用即插即用。UPNP端口映射將一個外部端口映射到一個內(nèi)網(wǎng)ip:port。從而實現(xiàn)p2p網(wǎng)絡(luò)從外網(wǎng)能夠穿透網(wǎng)關(guān)訪問到內(nèi)網(wǎng)的bytomd節(jié)點。

UPNP協(xié)議

SSDP(Simple Service Discovery Protocol 簡單服務(wù)發(fā)現(xiàn)協(xié)議) GENA(Generic Event Notification Architecture 通用事件通知結(jié)構(gòu)) SOAP(Simple Object Access Protocol 簡單對象訪問協(xié)議) XML(Extensible Markup Language 可擴張標(biāo)記語言)

UPNP代碼

** p2p/upnp/upnp.go **

發(fā)現(xiàn)網(wǎng)絡(luò)中支持UPNP功能的設(shè)備

從網(wǎng)絡(luò)中發(fā)現(xiàn)支持UPNP功能的設(shè)備,并得到該設(shè)備的location和url等相關(guān)信息

type upnpNAT struct {
	serviceURL string // 設(shè)備的描述文件URL,用于得到該設(shè)備的描述信息
	ourIP      string // 節(jié)點本地ip地址
	urnDomain  string // 設(shè)備類型
}

func Discover() (nat NAT, err error) {
	ssdp, err := net.ResolveUDPAddr("udp4", "239.255.255.250:1900")
	if err != nil {
		return
	}
	conn, err := net.ListenPacket("udp4", ":0")
	if err != nil {
		return
	}
	socket := conn.(*net.UDPConn)
	defer socket.Close()

	err = socket.SetDeadline(time.Now().Add(3 * time.Second))
	if err != nil {
		return
	}

	st := "InternetGatewayDevice:1"

	// 多播請求:M-SEARCH SSDP協(xié)議定義的發(fā)現(xiàn)請求。
	buf := bytes.NewBufferString(
		"M-SEARCH * HTTP/1.1\r\n" +
			"HOST: 239.255.255.250:1900\r\n" +
			"ST: ssdp:all\r\n" +
			"MAN: \"ssdp:discover\"\r\n" +
			"MX: 2\r\n\r\n")
	message := buf.Bytes()
	answerBytes := make([]byte, 1024)
	for i := 0; i < 3; i++ {
		// 向239.255.255.250:1900發(fā)送一條多播請求
		_, err = socket.WriteToUDP(message, ssdp)
		if err != nil {
			return
		}
		// 如果從網(wǎng)絡(luò)中發(fā)現(xiàn)UPNP設(shè)備則會從239.255.255.250:1900收到響應(yīng)消息
		var n int
		n, _, err = socket.ReadFromUDP(answerBytes)
		for {
			n, _, err = socket.ReadFromUDP(answerBytes)
			if err != nil {
				break
			}
			answer := string(answerBytes[0:n])
			if strings.Index(answer, st) < 0 {
				continue
			}
			// HTTP header field names are case-insensitive.
			// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
			// 獲得設(shè)備location
			locString := "\r\nlocation:"
			answer = strings.ToLower(answer)
			locIndex := strings.Index(answer, locString)
			if locIndex < 0 {
				continue
			}
			loc := answer[locIndex+len(locString):]
			endIndex := strings.Index(loc, "\r\n")
			if endIndex < 0 {
				continue
			}
			// 獲得設(shè)備的描述url和設(shè)備類型
			locURL := strings.TrimSpace(loc[0:endIndex])
			var serviceURL, urnDomain string
			serviceURL, urnDomain, err = getServiceURL(locURL)
			if err != nil {
				return
			}
			var ourIP net.IP
			ourIP, err = localIPv4()
			if err != nil {
				return
			}
			nat = &upnpNAT{serviceURL: serviceURL, ourIP: ourIP.String(), urnDomain: urnDomain}
			return
		}
	}
	err = errors.New("UPnP port discovery failed.")
	return
}

添加端口映射

向upnp設(shè)備發(fā)送一條http post請求,將內(nèi)部網(wǎng)絡(luò)ip:port和外部網(wǎng)絡(luò)ip:port做映射

func (n *upnpNAT) AddPortMapping(protocol string, externalPort, internalPort int, description string, timeout int) (mappedExternalPort int, err error) {
	// A single concatenation would break ARM compilation.
	message := "\r\n" +
		"" + strconv.Itoa(externalPort)
	message += "" + protocol + ""
	message += "" + strconv.Itoa(internalPort) + "" +
		"" + n.ourIP + "" +
		"1"
	message += description +
		"" + strconv.Itoa(timeout) +
		""

	var response *http.Response
	response, err = soapRequest(n.serviceURL, "AddPortMapping", message, n.urnDomain)
	if response != nil {
		defer response.Body.Close()
	}
	if err != nil {
		return
	}

	// TODO: check response to see if the port was forwarded
	// log.Println(message, response)
	// JAE:
	// body, err := ioutil.ReadAll(response.Body)
	// fmt.Println(string(body), err)
	mappedExternalPort = externalPort
	_ = response
	return
}

刪除端口映射

向upnp設(shè)備發(fā)送一條http post請求,將內(nèi)部網(wǎng)絡(luò)ip:port和外部網(wǎng)絡(luò)ip:port刪除映射關(guān)系

func (n *upnpNAT) DeletePortMapping(protocol string, externalPort, internalPort int) (err error) {

	message := "\r\n" +
		"" + strconv.Itoa(externalPort) +
		"" + protocol + "" +
		""

	var response *http.Response
	response, err = soapRequest(n.serviceURL, "DeletePortMapping", message, n.urnDomain)
	if response != nil {
		defer response.Body.Close()
	}
	if err != nil {
		return
	}

	// TODO: check response to see if the port was deleted
	// log.Println(message, response)
	_ = response
	return
}

獲取映射后的公網(wǎng)地址

func (n *upnpNAT) GetExternalAddress() (addr net.IP, err error) {
	info, err := n.getExternalIPAddress()
	if err != nil {
		return
	}
	addr = net.ParseIP(info.externalIpAddress)
	return
}

func (n *upnpNAT) getExternalIPAddress() (info statusInfo, err error) {

	message := "\r\n" +
		""

	var response *http.Response
	response, err = soapRequest(n.serviceURL, "GetExternalIPAddress", message, n.urnDomain)
	if response != nil {
		defer response.Body.Close()
	}
	if err != nil {
		return
	}
	var envelope Envelope
	data, err := ioutil.ReadAll(response.Body)
	reader := bytes.NewReader(data)
	xml.NewDecoder(reader).Decode(&envelope)

	info = statusInfo{envelope.Soap.ExternalIP.IPAddress}

	if err != nil {
		return
	}

	return
}

到此,關(guān)于“Bytom怎么實現(xiàn)P2P網(wǎng)絡(luò)upnp端口映射”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
本文名稱:Bytom怎么實現(xiàn)P2P網(wǎng)絡(luò)upnp端口映射
地址分享:http://weahome.cn/article/jhcjid.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部