成功完成不同内网的通讯

This commit is contained in:
2025-10-15 14:13:50 +08:00
parent e5e8c1c19f
commit c52d5359e9
7 changed files with 338 additions and 35 deletions

View File

@@ -1,7 +1,12 @@
package p2p
import (
"fmt"
"net"
"net/http"
"strings"
"sync"
"time"
"github.com/ayflying/p2p/internal/service"
"github.com/gogf/gf/v2/os/gctx"
@@ -54,3 +59,117 @@ func New() *sP2P {
func init() {
service.RegisterP2P(New())
}
// 获取公网IP并判断类型ipv4/ipv6
func (s *sP2P) getPublicIPAndType() (ip string, ipType string, err error) {
// 公网IP查询接口多个备用
apis := []string{
"https://api.ip.sb/ip",
"https://ip.3322.net",
"https://ifconfig.cn",
}
client := http.Client{Timeout: 5 * time.Second}
for _, api := range apis {
resp, err := client.Get(api)
if err != nil {
continue
}
defer resp.Body.Close()
// 读取响应纯IP字符串
buf := make([]byte, 128)
n, err := resp.Body.Read(buf)
if err != nil {
continue
}
ip = strings.TrimSpace(string(buf[:n]))
if ip == "" {
continue
}
// 判断IP类型
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
continue // 无效IP格式
}
if parsedIP.To4() != nil {
return ip, "ipv4", nil // IPv4
} else if parsedIP.To16() != nil {
return ip, "ipv6", nil // IPv6
}
}
return "", "", fmt.Errorf("所有公网IP查询接口均失败")
}
// 只获取IPv4公网IP过滤IPv6结果
func (s *sP2P) getIPv4PublicIP() (string, error) {
// 优先使用只返回IPv4的API避免IPv6干扰
ipv4OnlyAPIs := []string{
//"https://api.ip.sb/ip",
"https://ip.3322.net",
//"https://ifconfig.cn",
}
client := http.Client{Timeout: 5 * time.Second}
for _, api := range ipv4OnlyAPIs {
resp, err := client.Get(api)
if err != nil {
continue
}
defer resp.Body.Close()
// 读取响应
buf := make([]byte, 128)
n, err := resp.Body.Read(buf)
if err != nil {
continue
}
ip := strings.TrimSpace(string(buf[:n]))
if ip == "" {
continue
}
// 严格验证是否为IPv4过滤IPv6
parsedIP := net.ParseIP(ip)
if parsedIP != nil && parsedIP.To4() != nil { // 确保是IPv4
return ip, nil
}
}
return "", fmt.Errorf("所有IPv4公网查询接口均失败或返回非IPv4地址")
}
// 过滤地址列表排除127.0.0.1回环地址
func (s *sP2P) filterLoopbackAddrs(addrStrs []string) []string {
var filtered []string
for _, addrStr := range addrStrs {
// 直接过滤包含127.0.0.1的地址字符串
if strings.Contains(addrStr, "/ip4/127.0.0.1/") {
continue // 跳过回环地址
}
filtered = append(filtered, addrStr)
}
// 移除重复地址
filtered = s.removeDuplicates(filtered)
return filtered
}
// 去除字符串切片中的重复元素,保持首次出现的顺序
func (s *sP2P) removeDuplicates(strs []string) []string {
seen := make(map[string]bool) // 用于记录已出现的字符串
result := make([]string, 0, len(strs)) // 结果切片,预分配容量
for _, s := range strs {
if !seen[s] { // 如果未出现过
seen[s] = true // 标记为已出现
result = append(result, s) // 添加到结果
}
}
return result
}