同一局域网内,在不知道对方ip的情况下进行tcp连接(go语言实现)
程序员文章站
2022-05-16 20:58:23
...
业务场景:同一局域网内,在不知道对方ip的情况下,进行文件的传输。
实现方式:
- 规定连接端口
- 找到本机ip
- 遍历网段
由于存在本地实际ip和对外开放ip不同的情况(例:本地连有线,使用360wifi开的无线)
完整代码如下:
var remoteCon net.Conn
const Handle_Port = 5557
func GetRemoteCon() (net.Conn, error) {
if remoteCon == nil {
err := _startRemoteCon()
if err != nil {
return nil, err
}
} else {
err := CheckConnect(remoteCon, "start")
if err != nil {
log.Println("长在尝试重连")
er := _startRemoteCon()
if er != nil {
return nil, er
}
}
}
return remoteCon, nil
}
// 获取所有的ipv4地址
func LocalIPv4s() ([]string, error) {
var ips []string
addrs, err := net.InterfaceAddrs()
if err != nil {
return ips, err
}
for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
ips = append(ips, ipnet.IP.String())
}
}
return ips, nil
}
func _startRemoteCon() error {
ips, err := LocalIPv4s()
if err != nil {
return err
}
for _, ip := range ips {
con := _syncConLan(ip)
if con != nil {
remoteCon = con
return nil
}
}
return errors.New("未连接成功,请检查服务是否已启动")
}
// 若5557端口被占用,该情况暂未处理
func _syncConLan(ip string) (net.Conn) {
index := strings.LastIndex(ip, ".")
format := fmt.Sprintf("%s.%%d:%d", ip[:index], Handle_Port)
s := time.Now()
length := 254
wg := &sync.WaitGroup{}
ch := make(chan net.Conn, length)
for i := 0; i <= length; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
con, err := net.DialTimeout("tcp", fmt.Sprintf(format, i), time.Millisecond*500)
if err != nil {
return
}
err = CheckConnect(con, "start")
if err != nil {
return
}
ch <- con
}(i)
}
wg.Wait()
if len(ch) <= 0 {
return nil
}
res := make([]net.Conn, 0)
for i := 0; i < len(ch); i++ {
res = append(res, <-ch)
}
return res[0]
}
func CheckConnect(client net.Conn, str string) (err error) {
_, err = client.Write([]byte(str))
if err != nil {
common.Log.Info(err)
return
}
buf := make([]byte, 1024)
size, err := client.Read(buf)
if err != nil {
common.Log.Info(err)
return
}
var status = string(buf[0:size])
if status != "ok" {
err = errors.New("connect failed")
return
}
return
}