首页 > 其他分享 >godoos 内网聊天机制详解

godoos 内网聊天机制详解

时间:2024-12-12 21:54:02浏览次数:2  
标签:godoos return err nil 文件传输 用户 详解 聊天 msg

GodoOS 是一款轻量级的云桌面系统,旨在为用户提供高效、安全的网络通信环境。其内网聊天功能不仅支持文本消息的实时传输,还具备文件传输的能力。本文将详细介绍 godoos 内网聊天机制的核心原理和技术实现。

内网聊天机制概述

godoos 的内网聊天机制基于 UDP 协议,通过定期检查在线用户并维护一个在线用户列表,确保消息只能发送给当前在线的用户。此外,文件传输功能需要用户明确同意接收,以保证数据的安全性和用户的隐私。

ARP 发现在线 IP

  • godoos 使用 ARP 协议定期扫描局域网内的所有设备,发现在线的 IP 地址。
  • 这一过程通过 CheckOnlines 函数实现,该函数每 15 秒(可配置)调用一次 CheckOnline 方法,检查客户端是否已断开连接。
func getArpCacheIPs() ([]string, error) {
	var cmd *exec.Cmd
	var out []byte
	var err error

	switch runtime.GOOS {
	case "windows":
		cmd = exec.Command("arp", "-a")
	case "linux":
		cmd = exec.Command("arp", "-n")
	case "darwin": // macOS
		cmd = exec.Command("arp", "-l", "-a")
	default:
		return nil, fmt.Errorf("unsupported operating system: %v", runtime.GOOS)
	}

	out, err = cmd.Output()
	if err != nil {
		return nil, fmt.Errorf("error executing arp command: %v", err)
	}

	lines := strings.Split(string(out), "\n")
	var ips []string

	for _, line := range lines {
		fields := strings.Fields(line)
		if len(fields) >= 2 {
			ip := fields[0]
			if ip != "<incomplete>" && net.ParseIP(ip) != nil {
				ips = append(ips, ip)
			}
		}
	}

	return ips, nil
}

维护在线用户列表

  • 所有在线的用户信息被存储在 OnlineUsers 字典中,包括主机名、IP 地址、最后活跃时间等。
  • 当用户发送心跳消息(类型为 heartbeat)时,系统会更新该用户的在线状态。
func concurrentGetIpInfo(ips []string) {
	// 获取本地 IP 地址
	hostips, err := libs.GetValidIPAddresses()
	if err != nil {
		log.Printf("failed to get local IP addresses: %v", err)
		return
	}
	// 获取 ARP 缓存中的 IP 地址
	validIPs, err := getArpCacheIPs()
	if err != nil {
		log.Printf("failed to get ARP cache IPs: %v", err)
		return
	}
	var wg sync.WaitGroup
	maxConcurrency := runtime.NumCPU()

	semaphore := make(chan struct{}, maxConcurrency)

	failedIPs := make(map[string]bool)

	for _, ip := range ips {
		if containArr(hostips, ip) || failedIPs[ip] || !containArr(validIPs, ip) {
			continue
		}

		wg.Add(1)
		semaphore <- struct{}{}

		go func(ip string) {
			defer wg.Done()
			defer func() { <-semaphore }()
			err := sendUDPPacket(ip)
			if err != nil {
				log.Printf("Failed to send packet to IP %s: %v", ip, err)
				failedIPs[ip] = true // 标记失败的 IP
			}
		}(ip)
	}

	wg.Wait()
}

func CheckOnline() {
	// 清除 OnlineUsers 映射表
	CleanOnlineUsers()

	ips := libs.GetChatIPs()
	// 启动并发处理
	concurrentGetIpInfo(ips)

	log.Printf("online users: %v", OnlineUsers)
}

func CleanOnlineUsers() {
	OnlineUsers = make(map[string]UserStatus)
}

消息传输

UDP 服务器

  • godoos 在 UDP 端口 56780 上启动一个监听服务,接收来自客户端的消息。
  • 接收到的消息首先进行 JSON 解析,提取出消息类型、发送方 IP 地址等信息。
func UdpServer() {
	// 监听 UDP 端口
	listener, err := net.ListenPacket("udp", ":56780")
	if err != nil {
		log.Fatalf("error setting up listener: %v", err)
	}
	defer listener.Close()

	log.Println("UDP server started on :56780")

	// 监听 UDP 请求
	for {
		buffer := make([]byte, 1024)

		n, remoteAddr, err := listener.ReadFrom(buffer)
		if err != nil {
			log.Printf("error reading from UDP: %v", err)
			continue
		}

		log.Printf("Received UDP packet from %v: %s", remoteAddr, buffer[:n])
		// 从 remoteAddr 获取 IP 地址
		udpAddr, ok := remoteAddr.(*net.UDPAddr)
		if !ok {
			log.Printf("unexpected address type: %T", remoteAddr)
			continue
		}
		ip := udpAddr.IP.String()
		// 解析 UDP 数据
		var udpMsg UdpMessage
		err = json.Unmarshal(buffer[:n], &udpMsg)
		if err != nil {
			log.Printf("error unmarshalling UDP message: %v", err)
			continue
		}
		udpMsg.IP = ip

		if udpMsg.Type == "heartbeat" {
			UpdateUserStatus(udpMsg.IP, udpMsg.Hostname)
			continue
		}

		if udpMsg.Type == "image" {
			filePath, err := ReceiveImg(udpMsg)
			if err != nil {
				log.Printf("error receiving image: %v", err)
				continue
			}
			udpMsg.Message = filePath
		}
		// 添加消息到 UserMessages
		AddMessage(udpMsg)

	}
}

消息处理

  • 根据消息类型,系统会调用相应的处理函数。例如,心跳消息用于更新用户状态,文件传输请求需要用户确认。
  • 所有消息会被存储在 UserMessages 字典中,以便后续查询和展示。

文件传输

  1. 文件发送请求

    • 用户发起文件发送请求时,系统会生成一条类型为 fileSending 的消息,并发送给目标用户。
    • 目标用户接收到请求后,可以选择接受或拒绝。
  2. 文件传输确认

    • 如果目标用户同意接收文件,系统会生成一条类型为 fileAccessed 的消息,通知发送方开始传输文件。
    • 文件传输完成后,系统会返回文件路径给发送方,确保文件传输成功。
  3. 文件传输取消

    • 用户也可以取消文件发送请求,系统会生成一条类型为 fileCannel 的消息,通知目标用户取消操作。

func HandlerApplySendFile(w http.ResponseWriter, r *http.Request) {
	var msg UdpMessage
	decoder := json.NewDecoder(r.Body)
	if err := decoder.Decode(&msg); err != nil {
		http.Error(w, "Invalid request body", http.StatusBadRequest)
		return
	}
	defer r.Body.Close()
	hostname, err := os.Hostname()
	if err != nil {
		libs.ErrorMsg(w, "HandleMessage error")
		return
	}
	msg.Hostname = hostname
	msg.Time = time.Now()
	msg.Type = "fileSending"
	SendToIP(msg)
	libs.SuccessMsg(w, nil, "请求文件发送成功")
}
func HandlerCannelFile(w http.ResponseWriter, r *http.Request) {
	var msg UdpMessage
	decoder := json.NewDecoder(r.Body)
	if err := decoder.Decode(&msg); err != nil {
		http.Error(w, "Invalid request body", http.StatusBadRequest)
		return
	}
	defer r.Body.Close()
	hostname, err := os.Hostname()
	if err != nil {
		libs.ErrorMsg(w, "HandleMessage error")
		return
	}
	msg.Hostname = hostname
	msg.Time = time.Now()
	msg.Type = "fileCannel"
	SendToIP(msg)
	libs.SuccessMsg(w, nil, "请求文件发送成功")
}
func HandlerAccessFile(w http.ResponseWriter, r *http.Request) {
	var msg UdpMessage
	decoder := json.NewDecoder(r.Body)
	if err := decoder.Decode(&msg); err != nil {
		libs.ErrorMsg(w, "Invalid request body")
		return
	}
	defer r.Body.Close()
	hostname, err := os.Hostname()
	if err != nil {
		libs.ErrorMsg(w, "HandleMessage error")
		return
	}
	msg.Hostname = hostname
	msg.Time = time.Now()
	msg.Type = "fileAccessed"
	SendToIP(msg)
	path, err := downloadFiles(msg)
	if err != nil {
		libs.ErrorMsg(w, "HandleMessage error")
		return
	}
	res := map[string]interface{}{
		"path": path,
		"msg":  msg.Message,
	}
	libs.SuccessMsg(w, res, "接收文件成功")
}

安全与隐私

  • 用户确认机制:文件传输需要目标用户明确同意,确保数据的安全性和用户的隐私。
  • 在线状态检查:系统定期检查在线用户,确保消息只能发送给当前在线的用户,避免无效消息的传输。

结语

godoos 的内网聊天机制通过高效的在线用户检测和严格的消息处理流程,确保了内网通信的实时性和安全性。无论是文本消息还是文件传输,用户都能享受到便捷、可靠的通信体验。未来,godoos 将继续优化这一机制,为用户提供更加完善的内网通信解决方案。

标签:godoos,return,err,nil,文件传输,用户,详解,聊天,msg
From: https://www.cnblogs.com/xpbb/p/18603520

相关文章

  • 微信聊天快捷回复工具
    易歪歪是一款可以应付各种场景下聊天快捷回复工具,相对强大的客服聊天助手,支持话术存储,软件用于提升客服聊天效率,高标准统一迅捷回复,达到一名客服效率为五名的效益转化。软件特点一键发送话术,少打字,回复快支持图文视频文件,客服快速回复的神器,高效率接待智能吸附聊天窗口......
  • 微信聊天快捷回复工具
    易歪歪是一款可以应付各种场景下聊天快捷回复工具,相对强大的客服聊天助手,支持话术存储,软件用于提升客服聊天效率,高标准统一迅捷回复,达到一名客服效率为五名的效益转化。软件特点一键发送话术,少打字,回复快支持图文视频文件,客服快速回复的神器,高效率接待智能吸附聊天窗口......
  • 微信聊天快捷回复工具
    易歪歪是一款可以应付各种场景下聊天快捷回复工具,相对强大的客服聊天助手,支持话术存储,软件用于提升客服聊天效率,高标准统一迅捷回复,达到一名客服效率为五名的效益转化。软件特点一键发送话术,少打字,回复快支持图文视频文件,客服快速回复的神器,高效率接待智能吸附聊天窗口......
  • 微信聊天快捷回复工具
    易歪歪是一款可以应付各种场景下聊天快捷回复工具,相对强大的客服聊天助手,支持话术存储,软件用于提升客服聊天效率,高标准统一迅捷回复,达到一名客服效率为五名的效益转化。软件特点一键发送话术,少打字,回复快支持图文视频文件,客服快速回复的神器,高效率接待智能吸附聊天窗口......
  • Transformers 框架 Pipeline 任务详解(三):词元分类(token-classification)和命名实体识别
    微信公众号:老牛同学公众号标题:Transformers框架Pipeline任务详解(三):词元分类(token-classification)和命名实体识别公众号链接:https://mp.weixin.qq.com/s/r2uFCwPZaMeDL_eiQsEmIQ在自然语言处理(NLP)领域,Token-Classification(词元分类)任务是一项关键的技术,这项技术广泛应用于......
  • Vue 组件样式作用域和深度选择器详解
    1.问题背景在Vue项目中使用第三方组件库(如ElementUI)时,经常会遇到需要覆盖组件默认样式的情况。但是当我们在组件中使用<stylescoped>时,会发现样式无法生效。比如以下场景:<template><div><el-message-box>...</el-message-box></div></template><styles......
  • 常见漏洞篇——反序列化漏洞详解_反序列漏洞原理
    网络安全常见漏洞篇反序列化漏洞反序列化漏洞(DeserializationVulnerability)是一种安全漏洞,存在于应用程序中对数据进行反序列化操作的过程中。当应用程序接收到外部传递的恶意序列化数据并进行反序列化时,攻击者可以利用这个漏洞执行未经授权的代码或导致应用程序受到攻击......
  • [C++] 继承详解
    目录前言演示用编译器及其标准DevC++6.7.5Redpanda C++14                           先 赞 后 看  养  成 习 惯  正文1、继承的概念与意义2、继承的使用 2.1继承的定义及语法2......
  • ubuntu网络配置工具netplan详解
     1.首先查看当前的 netplan配置文件:ls/etc/netplan/通常会有一个类似 01-netcfg.yaml 或 50-cloud-init.yaml 的文件。 2.编辑netplan配置文件firefly@firefly:~$vim/etc/netplan/01-netcfg.yamlnetwork:version:2renderer:networkdethernets:......
  • DGCRN模型数学原理及运算过程详解
    这是一份用于动态图卷积循环网络DGCRN模型理解的入门教程,采用论文公式与示例结合的方式阐述动态图的实现过程与图卷积GCN在RNN中的运用。本文关于数学原理部分不一定完全严谨,如有错误请在评论区指出。 模型来自论文:DynamicGraphConvolutionalRecurrentNetworkforTraf......