我是 https://github.com/sigcn/pg 仓库的作者。 经过几个月的努力,现在用 PG 写 P2P 网络程序似乎很简单了。 发帖希望
这是一个访问虚拟网络内节点 HTTP 服务的示例
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"time"
"github.com/sigcn/pg/disco"
"github.com/sigcn/pg/langs"
"github.com/sigcn/pg/p2p"
"github.com/sigcn/pg/peermap/network"
"github.com/sigcn/pg/vpn"
"github.com/sigcn/pg/vpn/nic"
"github.com/sigcn/pg/vpn/nic/gvisor"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
)
var (
server = "wss://openpg.in/pg"
secretFile = "psns.json"
_, ip4, _ = net.ParseCIDR("100.99.0.27/24")
)
// prepareSecret 准备 JSONSecret 用于加入 PG 网络
func prepareSecret() error {
fetchSecret := func() error {
join, err := network.JoinOIDC("", server)
if err != nil {
return err
}
fmt.Println("Open the following link to authenticate")
fmt.Println(join.AuthURL())
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
secret, err := join.Wait(ctx)
cancel()
if err != nil {
panic(err)
}
f, err := os.Create(secretFile)
if err != nil {
return err
}
json.NewEncoder(f).Encode(secret)
return nil
}
f, err := os.Open(secretFile)
if err != nil {
return fetchSecret()
}
var secret disco.NetworkSecret
if err := json.NewDecoder(f).Decode(&secret); err != nil {
return err
}
if time.Now().After(secret.Expire) {
return fetchSecret()
}
return nil
}
// startVPN 启动 VPN (gVisor + p2p)
func startVPN(ctx context.Context) *gvisor.GvisorCard {
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol},
})
vnic := nic.VirtualNIC{NIC: &gvisor.GvisorCard{Stack: s, Config: nic.Config{IPv4: ip4.String()}}}
packetConn := langs.Must(p2p.ListenPacket(
&disco.Server{Secret: &disco.FileSecretStore{StoreFilePath: secretFile}, URL: server},
p2p.ListenPeerUp(func(pi disco.PeerID, v url.Values) {
vnic.AddPeer(nic.Peer{Addr: pi, IPv4: v.Get("alias1"), IPv6: v.Get("alias2"), Meta: v})
}),
p2p.ListenPeerSecure(),
p2p.PeerAlias1(ip4.IP.String()),
))
go vpn.New(vpn.Config{MTU: 1371}).Run(ctx, &vnic, packetConn)
return vnic.NIC.(*gvisor.GvisorCard)
}
func main() {
// 获取 JSONSecret
if err := prepareSecret(); err != nil {
panic(err)
}
// 启动 gVisor VPN
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
gvisorCard := startVPN(ctx)
// HTTP 请求
cli := http.Client{
Transport: &http.Transport{DialContext: gvisorCard.DialContext},
Timeout: 15 * time.Second,
}
r := langs.Must(cli.Get("http://100.99.0.2"))
defer r.Body.Close()
io.Copy(os.Stdout, r.Body)
}
![]() |
1
lekai63 16 小时 44 分钟前
感谢。但似乎一下没想到很赞的使用场景。。
|
![]() |
2
lizhenda 16 小时 42 分钟前
什么场景适用呢? 做个相关的 demo 是不是更好点。
|
3
lloovve 15 小时 17 分钟前 via iPhone
Ipv6 下,两个 5g 或者 4g 手机能直连么
|
![]() |
4
kk2syc 12 小时 26 分钟前 ![]() 我只能想到用你的 pg 复刻一个 qvod ,当年欠快播一个会员
|
![]() |
5
wangtian2020 4 小时 31 分钟前
webrtc p2p 已经很成熟了,为什么其他语言不 all in 呢
|
6
iYume 3 小时 14 分钟前
之前搞区块链时 libp2p 和 devp2p 都用过,你的介绍说的 nat / 25519 这些其他库也都有,我并不算特别了解,只是觉得在 README 搞个 vs. 块对比一下特性可能会便于大家直观看出来
|
7
zzhirong 56 分钟前
1. 看到 PG 第一反应联想到 PostgreSQL 。
2. 在阅读 README 时,我发现了一个有趣的词——“Birthday Paradox (生日悖论,在一个群体中,只需要 23 个人,就有超过 50% 的概率存在两个人的生日相同)”,用在 NAT 穿越上,指的是在双方都知道对方 NAT 地址但不知道对方 NAT 映射端口的情况下,各自随机选择一组目标端口发起通信,从而有一定概率能建立连接,这不禁让人联想到你我相识全靠缘分。最近刚好看了两个关于概率相关的数据结构:跳跃表和 HyperLogLog 。感叹数学真美和烧脑。 |
![]() |
8
lujiaxing 23 分钟前
国内大概没啥用. 国内封得厉害. 连 WebRTC 都连不上更何况你这
|