同一局域网内,在不知道对方ip的情况下进行tcp连接(go语言实现)

业务场景:同一局域网内,在不知道对方ip的情况下,进行文件的传输。

实现方式:

  1. 规定连接端口
  2. 找到本机ip
  3. 遍历网段

由于存在本地实际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
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值