package p2p
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名申請(qǐng)、雅安服務(wù)器托管、營(yíng)銷軟件、網(wǎng)站建設(shè)、迎澤網(wǎng)站維護(hù)、網(wǎng)站推廣。
import (
"context"
"errors"
"time"
net "gx/ipfs/QmPjvxTpVH8qJyQDnxnsxF9kv9jezKD1kozz1hs3fCGsNh/go-libp2p-net"
manet "gx/ipfs/QmV6FjemM1K8oXjrvuq3wuVWWoU2TLDPmNnKrxHzY3v6Ai/go-multiaddr-net"
ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr"
pro "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol"
pstore "gx/ipfs/QmZR2XWVVBCtbgBWnQhWk2xcQfaR3W8faQPriAiaaj7rsr/go-libp2p-peerstore"
p2phost "gx/ipfs/Qmb8T6YBBsjYsVGfrihQLfCJveczZnneSBqBKkYEBWDjge/go-libp2p-host"
peer "gx/ipfs/QmdVrMn1LhB4ybb8hMVaMLXnA8XRSewMnK6YqXKXoTcRvN/go-libp2p-peer"
)
//P2P結(jié)構(gòu)保存當(dāng)前正在運(yùn)行的流/監(jiān)聽(tīng)器的信息
// P2P structure holds information on currently running streams/listeners
type P2P struct {
//監(jiān)聽(tīng)器
Listeners ListenerRegistry
//數(shù)據(jù)流
Streams StreamRegistry
//節(jié)點(diǎn)ID
identity peer.ID
//節(jié)點(diǎn)地址
peerHost p2phost.Host
//一個(gè)線程安全的對(duì)等節(jié)點(diǎn)存儲(chǔ)
peerstore pstore.Peerstore
}
//創(chuàng)建一個(gè)新的p2p結(jié)構(gòu)
// NewP2P creates new P2P struct
//這個(gè)新的p2p結(jié)構(gòu)不包含p2p結(jié)構(gòu)中的監(jiān)聽(tīng)器和數(shù)據(jù)流
func NewP2P(identity peer.ID, peerHost p2phost.Host, peerstore pstore.Peerstore) *P2P {
return P2P{
identity: identity,
peerHost: peerHost,
peerstore: peerstore,
}
}
//新建一個(gè)數(shù)據(jù)流 工具方法 構(gòu)建一個(gè)有節(jié)點(diǎn)id,內(nèi)容和協(xié)議的流
func (p2p P2P) newStreamTo(ctx2 context.Context, p peer.ID, protocol string) (net.Stream, error) {
//30s 后會(huì)自動(dòng)timeout
ctx, cancel := context.WithTimeout(ctx2, time.Second 30) //TODO: configurable?
defer cancel()
err := p2p.peerHost.Connect(ctx, pstore.PeerInfo{ID: p})
if err != nil {
return nil, err
}
return p2p.peerHost.NewStream(ctx2, p, pro.ID(protocol))
}
//對(duì)話為遠(yuǎn)程監(jiān)聽(tīng)器創(chuàng)建新的P2P流
//創(chuàng)建一個(gè)新的p2p流實(shí)現(xiàn)對(duì)對(duì)話的監(jiān)聽(tīng)
// Dial creates new P2P stream to a remote listener
//Multiaddr是一種跨協(xié)議、跨平臺(tái)的表示格式的互聯(lián)網(wǎng)地址。它強(qiáng)調(diào)明確性和自我描述。
//對(duì)內(nèi)接收
func (p2p P2P) Dial(ctx context.Context, addr ma.Multiaddr, peer peer.ID, proto string, bindAddr ma.Multiaddr) ( ListenerInfo, error) {
//獲取一些節(jié)點(diǎn)信息 network, host, nil
lnet, _, err := manet.DialArgs(bindAddr)
if err != nil {
return nil, err
}
//監(jiān)聽(tīng)信息
listenerInfo := ListenerInfo{
//節(jié)點(diǎn)身份
Identity: p2p.identity,
////應(yīng)用程序協(xié)議標(biāo)識(shí)符。
Protocol: proto,
}
//調(diào)用newStreamTo 通過(guò)ctx(內(nèi)容) peer(節(jié)點(diǎn)id) proto(協(xié)議標(biāo)識(shí)符) 參數(shù)獲取一個(gè)新的數(shù)據(jù)流
remote, err := p2p.newStreamTo(ctx, peer, proto)
if err != nil {
return nil, err
}
//network協(xié)議標(biāo)識(shí)
switch lnet {
//network為"tcp", "tcp4", "tcp6"
case "tcp", "tcp4", "tcp6":
//從監(jiān)聽(tīng)器獲取新的信息 nla.Listener, nil
listener, err := manet.Listen(bindAddr)
if err != nil {
if err2 := remote.Reset(); err2 != nil {
return nil, err2
}
return nil, err
}
//將獲取的新信息保存到listenerInfo
listenerInfo.Address = listener.Multiaddr()
listenerInfo.Closer = listener
listenerInfo.Running = true
//開(kāi)啟接受
go p2p.doAccept(listenerInfo, remote, listener)
default:
return nil, errors.New("unsupported protocol: " + lnet)
}
return listenerInfo, nil
}
//
func (p2p *P2P) doAccept(listenerInfo *ListenerInfo, remote net.Stream, listener manet.Listener) {
//關(guān)閉偵聽(tīng)器并刪除流處理程序
defer listener.Close()
//Returns a Multiaddr friendly Conn
//一個(gè)有好的 Multiaddr 連接
local, err := listener.Accept()
if err != nil {
return
}
stream := StreamInfo{
//連接協(xié)議
Protocol: listenerInfo.Protocol,
//定位節(jié)點(diǎn)
LocalPeer: listenerInfo.Identity,
//定位節(jié)點(diǎn)地址
LocalAddr: listenerInfo.Address,
//遠(yuǎn)程節(jié)點(diǎn)
RemotePeer: remote.Conn().RemotePeer(),
//遠(yuǎn)程節(jié)點(diǎn)地址
RemoteAddr: remote.Conn().RemoteMultiaddr(),
//定位
Local: local,
//遠(yuǎn)程
Remote: remote,
//注冊(cè)碼
Registry: p2p.Streams,
}
//注冊(cè)連接信息
p2p.Streams.Register(stream)
//開(kāi)啟節(jié)點(diǎn)廣播
stream.startStreaming()
}
//偵聽(tīng)器將流處理程序包裝到偵聽(tīng)器中
// Listener wraps stream handler into a listener
type Listener interface {
Accept() (net.Stream, error)
Close() error
}
//P2PListener保存關(guān)于偵聽(tīng)器的信息
// P2PListener holds information on a listener
type P2PListener struct {
peerHost p2phost.Host
conCh chan net.Stream
proto pro.ID
ctx context.Context
cancel func()
}
//等待偵聽(tīng)器的連接
// Accept waits for a connection from the listener
func (il *P2PListener) Accept() (net.Stream, error) {
select {
case c := -il.conCh:
return c, nil
case -il.ctx.Done():
return nil, il.ctx.Err()
}
}
//關(guān)閉偵聽(tīng)器并刪除流處理程序
// Close closes the listener and removes stream handler
func (il *P2PListener) Close() error {
il.cancel()
il.peerHost.RemoveStreamHandler(il.proto)
return nil
}
// Listen創(chuàng)建新的P2PListener
// Listen creates new P2PListener
func (p2p P2P) registerStreamHandler(ctx2 context.Context, protocol string) ( P2PListener, error) {
ctx, cancel := context.WithCancel(ctx2)
list := P2PListener{
peerHost: p2p.peerHost,
proto: pro.ID(protocol),
conCh: make(chan net.Stream),
ctx: ctx,
cancel: cancel,
}
p2p.peerHost.SetStreamHandler(list.proto, func(s net.Stream) {
select {
case list.conCh - s:
case -ctx.Done():
s.Reset()
}
})
return list, nil
}
// NewListener創(chuàng)建新的p2p偵聽(tīng)器
// NewListener creates new p2p listener
//對(duì)外廣播
func (p2p P2P) NewListener(ctx context.Context, proto string, addr ma.Multiaddr) ( ListenerInfo, error) {
//調(diào)用registerStreamHandler 構(gòu)造一個(gè)新的listener
listener, err := p2p.registerStreamHandler(ctx, proto)
if err != nil {
return nil, err
}
//構(gòu)造新的listenerInfo
listenerInfo := ListenerInfo{
Identity: p2p.identity,
Protocol: proto,
Address: addr,
Closer: listener,
Running: true,
Registry: p2p.Listeners,
}
go p2p.acceptStreams(listenerInfo, listener)
//注冊(cè)連接信息
p2p.Listeners.Register(listenerInfo)
return listenerInfo, nil
}
//接受流
func (p2p *P2P) acceptStreams(listenerInfo *ListenerInfo, listener Listener) {
for listenerInfo.Running {
//一個(gè)有好的 遠(yuǎn)程 連接
remote, err := listener.Accept()
if err != nil {
listener.Close()
break
}
}
//取消注冊(cè)表中的p2p偵聽(tīng)器
p2p.Listeners.Deregister(listenerInfo.Protocol)
}
// CheckProtoExists檢查是否注冊(cè)了協(xié)議處理程序
// mux處理程序
// CheckProtoExists checks whether a protocol handler is registered to
// mux handler
func (p2p *P2P) CheckProtoExists(proto string) bool {
protos := p2p.peerHost.Mux().Protocols()
for _, p := range protos {
if p != proto {
continue
}
return true
}
return false
}
任何一門計(jì)算機(jī)語(yǔ)言,都能在特定某個(gè)領(lǐng)域的應(yīng)用中,實(shí)現(xiàn)區(qū)塊鏈技術(shù);
具體使用哪一門語(yǔ)言,完全看我們相應(yīng)領(lǐng)域行業(yè)企業(yè)項(xiàng)目的技術(shù)要求,以及更關(guān)鍵的:跟已有信息系統(tǒng)的有效對(duì)接聯(lián)通。
區(qū)塊鏈具有自下而上生成記錄,生成兩方或多方合同類記錄,加入第三方確認(rèn)機(jī)制,分布存儲(chǔ),……等特點(diǎn);
從而讓它相比集中式的存儲(chǔ)運(yùn)算而言,變得更為可信。
常見(jiàn)的總統(tǒng)投票,就非常適合以區(qū)塊鏈技術(shù)重新架構(gòu);采用區(qū)塊鏈技術(shù)的投票系統(tǒng),能夠避免哪一家技術(shù)公司、某一個(gè)關(guān)鍵技術(shù)人員,操縱選票統(tǒng)計(jì)結(jié)果的可能。
像我們的法院證據(jù),也特別適合采用區(qū)塊鏈技術(shù)重新架構(gòu)開(kāi)發(fā)。
其實(shí)像當(dāng)前我們各類互聯(lián)網(wǎng)時(shí)代的“版權(quán)系統(tǒng)”,它們中一些就是采用區(qū)塊鏈技術(shù)架構(gòu)而來(lái),只不過(guò),目前我們的新聞出版局、專利局(或者更廣義地被稱作“專家評(píng)委”),都尚未接入這些由互聯(lián)網(wǎng)公司創(chuàng)新而來(lái)的版權(quán)平臺(tái)。
我們耳熟能詳 的“法大大”(雖然名字不甚好聽(tīng)、甚至乍一聽(tīng)來(lái)有些讓人“摸不著頭腦”),它也其實(shí)正準(zhǔn)備采用最新的區(qū)塊鏈技術(shù)重新架構(gòu);采用區(qū)塊鏈技術(shù)的合同平臺(tái),因?yàn)樽兊酶涌尚牛膊拍芨阌诨ヂ?lián)網(wǎng)時(shí)代人們簽訂各類商務(wù)合同。
還有像我們的“征信系統(tǒng)”,也非常適合以區(qū)塊鏈技術(shù)加以改造。能夠讓它更有說(shuō)服力,而不致于出現(xiàn)一家單位、乃至隨意某個(gè)關(guān)鍵技術(shù)人員,能隨意往其中添加“征信污點(diǎn)數(shù)據(jù)”的情況。
還有像我們的P2P貸款,如果能夠以區(qū)塊鏈技術(shù)重新架構(gòu)的話,也能夠變得更加可信,而不致于出現(xiàn)違約、卷款跑路這樣的失信情況。
區(qū)塊鏈平臺(tái),是要看區(qū)塊鏈資訊的嗎,這里安利個(gè) 密碼財(cái)經(jīng),一般鏈圈幣圈dapp等信息都能看到。
1.1 簡(jiǎn)介
nps是一款輕量級(jí)、高性能、功能強(qiáng)大的內(nèi)網(wǎng)穿透代理服務(wù)器。目前支持tcp、udp流量轉(zhuǎn)發(fā),可支持任何tcp、udp上層協(xié)議(訪問(wèn)內(nèi)網(wǎng)網(wǎng)站、本地支付接口調(diào)試、ssh訪問(wèn)、遠(yuǎn)程桌面,內(nèi)網(wǎng)dns解析等等……),此外還支持內(nèi)網(wǎng)http代理、內(nèi)網(wǎng)socks5代理、p2p等,并帶有功能強(qiáng)大的web管理端。
一臺(tái)有公網(wǎng)IP的服務(wù)器(VPS)運(yùn)行服務(wù)端(NPS)
一個(gè)或多個(gè)運(yùn)行在內(nèi)網(wǎng)的服務(wù)器或者PC運(yùn)行客戶端(NPC)
?
1.2 特點(diǎn)
Go語(yǔ)言編寫
支持跨平臺(tái)
支持多種協(xié)議的代理
web管理端
1.3 使用方法
NPS
安裝配置
找到自己服務(wù)器相應(yīng)版本的server:
在nps目錄下面會(huì)有一個(gè)nps可執(zhí)行文件、conf配置目錄和web網(wǎng)頁(yè)目錄,我們只需要修改即可:
需要改一下下面的幾個(gè)參數(shù),
修改 可以更改 NPC的連接端口。比如我們拿到一臺(tái)權(quán)限受限的服務(wù)器,有防火墻,可能只有部分端口(80,443)可以出網(wǎng),就需要修改成出網(wǎng)端口。
啟動(dòng)
NPC
?
新建好客戶端后,也可以在中看到,詳細(xì)的客戶端連接命令:
web管理端
在客戶端界面可以通過(guò)的方式添加客戶端連接,每一個(gè)連接的vkey都是唯一區(qū)分的。
每一個(gè)客戶端,在建立連接后,都可以建立多個(gè)不同協(xié)議的隧道,這一個(gè)個(gè)隧道就是不同的代理了。
通過(guò)不同的協(xié)議和端口就可以連接代理的內(nèi)網(wǎng)機(jī)器。
frp
2.1 簡(jiǎn)介
frp 是一個(gè)專注于內(nèi)網(wǎng)穿透的高性能的反向代理應(yīng)用,支持 TCP、UDP、HTTP、HTTPS 等多種協(xié)議。可以將內(nèi)網(wǎng)服務(wù)以安全、便捷的方式通過(guò)具有公網(wǎng) IP 節(jié)點(diǎn)的中轉(zhuǎn)暴露到公網(wǎng)。
?
2.2 特點(diǎn)
客戶端服務(wù)端通信支持 TCP、KCP 以及 Websocket 等多種協(xié)議。
端口復(fù)用,多個(gè)服務(wù)通過(guò)同一個(gè)服務(wù)端端口暴露。
跨平臺(tái),但是支持的比nps少一點(diǎn)
多種插件,提供很多功能
2.3 使用方法
下載:
以下內(nèi)容摘自:
1. 通過(guò) rdp 訪問(wèn)家里的機(jī)器
1.修改 frps.ini 文件,為了安全起見(jiàn),這里最好配置一下身份驗(yàn)證,服務(wù)端和客戶端的 common 配置中的 參數(shù)一致則身份驗(yàn)證通過(guò):
2. 啟動(dòng) frps:
3. 修改 frpc.ini 文件,假設(shè) frps 所在服務(wù)器的公網(wǎng) IP 為 x.x.x.x:
4. 啟動(dòng) frpc:
5.通過(guò) rdp 訪問(wèn)遠(yuǎn)程的機(jī)器,地址為:
開(kāi)機(jī)自啟
針對(duì) Windows 系統(tǒng),為了便于使用,可以配置一下開(kāi)機(jī)的時(shí)候靜默啟動(dòng)。
1.在 frpc.exe 的同級(jí)目錄創(chuàng)建一個(gè) start_frpc.vbs:
2.復(fù)制 start_frpc.vbs 文件,打開(kāi)以下目錄,注意將
改為你的用戶名:
3.鼠標(biāo)右擊,粘貼為快捷方式即可。
2. 通過(guò) SSH 訪問(wèn)公司內(nèi)網(wǎng)機(jī)器
frps 的部署步驟同上。
1.啟動(dòng) frpc,配置如下:
2.通過(guò) SSH 訪問(wèn)內(nèi)網(wǎng)機(jī)器,假設(shè)用戶名為 test:
3. 通過(guò)自定義域名訪問(wèn)部署于內(nèi)網(wǎng)的 Web 服務(wù)
有時(shí)想要讓其他人通過(guò)域名訪問(wèn)或者測(cè)試我們?cè)诒镜卮罱ǖ?Web 服務(wù),但是由于本地機(jī)器沒(méi)有公網(wǎng) IP,無(wú)法將域名解析到本地的機(jī)器,通過(guò) frp 就可以實(shí)現(xiàn)這一功能,以下示例為 http 服務(wù),https 服務(wù)配置方法相同, vhost_http_port 替換為 vhost_https_port, type 設(shè)置為 https 即可。
1.修改 frps.ini 文件,設(shè)置 http 訪問(wèn)端口為 8080:
2.啟動(dòng) frps:
3.修改 frpc.ini 文件,假設(shè) frps 所在的服務(wù)器的 IP 為 x.x.x.x,local_port 為本地機(jī)器上 Web 服務(wù)對(duì)應(yīng)的端口, 綁定自定義域名 :
4.啟動(dòng) frpc:
5.將 的域名 A 記錄解析到 IP ,如果服務(wù)器已經(jīng)有對(duì)應(yīng)的域名,也可以將 CNAME 記錄解析到服務(wù)器原先的域名。
6.通過(guò)瀏覽器訪問(wèn) 即可訪問(wèn)到處于內(nèi)網(wǎng)機(jī)器上的 Web 服務(wù)。
4. 對(duì)外提供簡(jiǎn)單的文件訪問(wèn)服務(wù)
通過(guò) 插件可以對(duì)外提供一個(gè)簡(jiǎn)單的基于 HTTP 的文件訪問(wèn)服務(wù)。
frps 的部署步驟同上。
1.啟動(dòng) frpc,啟用 插件,配置如下:
2.通過(guò)瀏覽器訪問(wèn) 來(lái)查看位于 目錄下的文件,會(huì)要求輸入已設(shè)置好的用戶名和密碼。
常用功能
統(tǒng)計(jì)面板(Dashboard)
通過(guò)瀏覽器查看 frp 的狀態(tài)以及代理統(tǒng)計(jì)信息展示。
注:Dashboard 尚未針對(duì)大量的 proxy 數(shù)據(jù)展示做優(yōu)化,如果出現(xiàn) Dashboard 訪問(wèn)較慢的情況,請(qǐng)不要啟用此功能。
需要在 frps.ini 中指定 dashboard 服務(wù)使用的端口,即可開(kāi)啟此功能:
打開(kāi)瀏覽器通過(guò) 訪問(wèn) dashboard 界面,用戶名密碼默認(rèn)為 。
加密與壓縮
這兩個(gè)功能默認(rèn)是不開(kāi)啟的,需要在 frpc.ini 中通過(guò)配置來(lái)為指定的代理啟用加密與壓縮的功能,壓縮算法使用 snappy:
如果公司內(nèi)網(wǎng)防火墻對(duì)外網(wǎng)訪問(wèn)進(jìn)行了流量識(shí)別與屏蔽,例如禁止了 SSH 協(xié)議等,通過(guò)設(shè)置 ,將 frpc 與 frps 之間的通信內(nèi)容加密傳輸,將會(huì)有效防止流量被攔截。
如果傳輸?shù)膱?bào)文長(zhǎng)度較長(zhǎng),通過(guò)設(shè)置 對(duì)傳輸內(nèi)容進(jìn)行壓縮,可以有效減小 frpc 與 frps 之間的網(wǎng)絡(luò)流量,加快流量轉(zhuǎn)發(fā)速度,但是會(huì)額外消耗一些 CPU 資源。
P2P就是網(wǎng)上理財(cái)?shù)囊粋€(gè)平臺(tái),兩個(gè)不認(rèn)識(shí)的人通過(guò)這個(gè)平臺(tái)達(dá)到借款和理財(cái)。是可以賺到錢的,收益相對(duì)于銀行更高些,各方面很靈活,比如說(shuō)直接網(wǎng)上操作,100元就可以投了,操作起來(lái)很簡(jiǎn)單。推薦您鑫華士這個(gè)平臺(tái)。