go记录:同一局域网内的tcp连接,断网后,Read不能及时响应

需求描述

PC 能够检测到同一局域网中已连接的手机,并记录连接状态。

实现方式

  1. 第一时间想到的是 ping 的方式,但是同一局域网内,可能有很多连接着的设备,不能确定能够 ping 通的设备是否是需要连接的设备,这里推荐一个开源库 fastping,实现了 ping 的功能,简单实用。
  2. 手机和 PC 建立 tcp 连接,通过指定命令进行交互。
    PC 发送 start 至 手机,手机接收到后返回 ok,进行一次简单的交互判断。

问题描述

手机 app 作为服务端,在同一局域网内,PC 连接上手机 tcp 服务后,阻塞读取手机消息(手机一直不回传消息)。
手机断网,PCconn.Read 方法不会直接错误退出(会在大约3分钟后退出,和操作系统有关,源码注释)。
手机主动 close 结束 tcp 连接,则 PC 端会直接错误退出。

代码示例

go 客户端,使用 conn.Read 方法进行连接的判断。

func client() {
	conn, err :=  net.DialTimeout("tcp", "172.16.10.85:3485", time.Second * 3)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer conn.Close()

	fmt.Println("有连接: ", conn.RemoteAddr())
	fmt.Println("当前时间: ", time.Now().String())
	defer func() {
		fmt.Println("结束时间:", time.Now().String())
	} ()
	buf := make([]byte, 1024)
	n, err := conn.Read(buf) // 理想状态下,连接没断开,这边会一直卡住。当连接断开,会直接错误退出
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("read: ", string(buf[:n]))
}

解决方式

直接通过 start ok 的交互来判断连接的存在。这里考虑到了网络波动,会尝试重新建立新的连接。

func (this *AgentService)listenConLeft(con net.Conn, multiId string) {
	if con == nil {
		common.Log.Info("con is nil")
		return
	}
	addr := con.RemoteAddr().String()
	defer func() {
		if er := recover(); er != nil {
			this.deleteDevice(addr)
		}
	}()

	//con.Read() // 使用read卡住,断网不会立即响应
	duration := time.Second * 5
	ticker := time.NewTicker(duration)
	defer ticker.Stop()
	for range ticker.C {
		err := CheckConnect(con, "start", duration)
		if err != nil {
			if con != nil {
				con.Close()
			}
			// 若没查询到手机,则直接尝试建立新的连接
			con, err = net.DialTimeout("tcp", addr, duration)
			if err != nil {
				this.deleteDevice(addr)
				return
			}

			// 正常情况下,手机断网再重新接入网络,ip地址是不会变化的,设备信息也就不会变化。
			// 这边考虑ip地址若变化的情况,需要检测下设备信息
			curMultiId, err := GetAgentDeviceMultiId(con)
			if err != nil {
				this.deleteDevice(addr)
				return
			}
			if curMultiId != multiId {
				this.deleteDevice(addr)
				return
			}
		}
	}
}

总结

PC 作为客户端,手机作为服务端,PC 扫描连接手机的方式,由于网络问题,可能会出现各种情况,不能实时的判断手机的在线状态,可以通过其他的设计方式来规避这种技术问题,如:切换一下方式,PC 作为服务端,提供一个二维码(ip),来让手机进行扫码连接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值