Ubuntu下Go语言TCP广播服务器实现

news2024/11/27 9:46:01

最近在学习Go语言网络编程,突然想到很久以前的用C语言写过的TCP广播聊天程序,然后就用Go尝试写了一遍,在此做个记录。

目录

1.广播结构

2.实现效果

3.源码

4.Go语言学习参考网站


1.广播结构

2.实现效果

服务器:

 客户端1:

 客户端2:

 客户端3:

3.源码

server.go

package main

import (
	"encoding/json"
	"fmt"
	"net"
	"strings"
)

// client info
type Client struct {
	Chan chan []byte
	Addr string
}

// 广播信息
type Msg struct {
	Content string
	User    string
}

// 客户端信息存储,IP和端口字符串为key
var onlineClients = make(map[string]Client)

// 广播消息的通道
var broadcastCh = make(chan Msg)

// 遍历通知客户端
func broadcastMessageManager() {
	for {
		//广播通道取数据
		msg := <-broadcastCh
		//遍历客户端发送数据
		for _, client := range onlineClients {
			msgBytes, _ := json.Marshal(msg)
			client.Chan <- msgBytes
		}
	}
}

// 接收客户端消息,并将消息放入广播消息通道
func readClient(conn net.Conn) {
	for true {
		data := make([]byte, 1024)
		n, _ := conn.Read(data)
		content := strings.TrimSpace(string(data[:n]))
		if len(content) <= 0 {
			continue
		}
		broadcastCh <- Msg{Content: content, User: conn.RemoteAddr().String()}
		fmt.Printf("%s say: %s\n", conn.RemoteAddr().String(), content)
	}
}

// 通知客户端消息
func notifyMsgToClient(conn net.Conn, client Client) {
	for {
		msgBytes := <-client.Chan
		_, _ = conn.Write(msgBytes)
	}
}

func handleConnect(conn net.Conn) {
	addr := conn.RemoteAddr().String()
	fmt.Println("connect cilent: ", conn.RemoteAddr().String())

	client := Client{make(chan []byte), addr}
	onlineClients[addr] = client

	content := client.Addr + " coming!"
	broadcastCh <- Msg{Content: content, User: "system info"}

	go readClient(conn)
	go notifyMsgToClient(conn, client)
}

func main() {
	fmt.Println("server starting ...")

	listener, err := net.Listen("tcp", "127.0.0.1:8181")
	if err != nil {
		fmt.Println("net.Listen err: ", err)
		return
	}

	//遍历通知客户端
	go broadcastMessageManager()

	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("listener.Accept err: ", err)
			continue
		}

		//goroutine处理用户连接
		go handleConnect(conn)
	}

}

client.go

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"net"
	"os"
)

// 广播信息
type Msg struct {
	Content string
	User    string
}

func readMsg(conn net.Conn) {
	for {

		res := make([]byte, 1024)
		n, err := conn.Read(res)
		if err != nil {
			fmt.Println(err)
			return
		}
		result := res[:n]
		var msg Msg
		json.Unmarshal(result, &msg)
		fmt.Printf("%s: %s\n", msg.User, msg.Content)
	}
}

func writeMsg(conn net.Conn) {
	for true {
		// 从标准输入生成读对象
		reader := bufio.NewReader(os.Stdin)
		// 读到换行
		content, _ := reader.ReadBytes('\n')
		if len(content) <= 0 {
			continue
		}
		// 发送数据
		conn.Write(content)
	}
}

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8181")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer conn.Close()

	// 起goroutine接收服务器广播的消息
	go readMsg(conn)

	// 命令行接收输入并发送给服务器
	writeMsg(conn)

}

4.Go语言学习参考网站

Go言入门教程:
http://c.biancheng.net/golang/

Go编程参考:
http://www.yuan316.com/post/Go%E8%AF%AD%E8%A8%80/

Go语言标准库:
https://pkg.go.dev/std

Go虎贲
https://www.zhihu.com/column/c_1438631789279076353

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/722174.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小程序 web-view h5页面背景音乐自动播放

/*** 年度账单-登录首页*/ import React,{useEffect} from react import swiper/swiper-bundle.min.css import styles from ./styles.less import bgm from ./bgm2.mp3 // 主体 const annualAccountLoginIndex (props) > {const goAnnualAccount ()>{const {location: …

Java Web Tomcat 23.7.5

Tomcat 1, Tomcat 1.1 简介 1.1.1 什么是Web服务器 Web服务器是一个应用程序&#xff08;软件&#xff09;&#xff0c;对HTTP协议的操作进行封装&#xff0c;使得程序员不必直接对协议进行操作&#xff0c;让Web开发更加便捷。主要功能是"提供网上信息浏览服务"…

[Python系列] Python虚拟环境Virtualenv

1. 什么是Virtualenv Python virtualenv 是一个用于创建和管理虚拟环境的工具。它可以帮助开发者在不同的项目中使用不同的 Python 版本和包&#xff0c;而不会相互干扰。使用 virtualenv&#xff0c;可以轻松地创建一个独立的 Python 环境&#xff0c;在其中安装所需的包和版本…

【网络】思科网络vlan配置+单臂路由

文章目录 前言一、vlan&#xff08;虚拟局域网&#xff09;二、配置vlan配置交换机0配置交换机1&#xff08;和交换机0相同&#xff09;配置计算机&#xff1a;测试联通性 三、单臂路由配置R0配置交换机1测试配置&#xff1a; 前言 VLAN&#xff08;Virtual Local Area Networ…

力扣 491. 递增子序列

题目来源&#xff1a;https://leetcode.cn/problems/non-decreasing-subsequences/description/ 回溯三部曲&#xff08;来源代码随想录&#xff09;&#xff1a; 递归函数参数&#xff1a;求子序列&#xff0c;很明显一个元素不能重复使用&#xff0c;所以需要startIndex&…

2023年 vue使用腾讯地图搜索、关键字输入提示、地点显示

先看结果 vue 在public文件下的index.html文件中引入&#xff1a; <script src"//map.qq.com/api/js?v2.exp&key你自己的key"></script><script src"https://map.qq.com/api/gljs?v1.exp&librariesservice&key你自己的key"&…

【保姆级教程】PyCharm通过SSH远程连接ModelArts

文章目录 一、创建Notebook二、配置SSH三、配置远程Python解释器四、成果展示 一、创建Notebook 首先&#xff0c;找到云资源下面的 ModelArts&#xff0c;然后点击并进入 ModelArts控制台。 在ModelArts控制台中&#xff0c;点击开发环境下的 Notebook 。然后点击创建&#x…

记录一次Nginx日志偶现499的排查

背景 查看到nginx日志在整点整分的时候频繁出现 499&#xff0c;因为配置了存活检查和就绪检查&#xff0c;担心业务会出现大面积重建导致现网故障&#xff0c;所以对出现499的原因进行排查&#xff0c;记录下排查思路&#xff0c;方便以后查看。 业务链路&#xff1a; 负载均…

B/S版手术麻醉系统源码,基于php、mysql和vue2开发

手术麻醉系统是一套以数字形式与医院信息系统&#xff08;如HIS、EMR、LIS、PACS等&#xff09;和医疗设备等软、硬件集成并获取围手术期相关信息的计算机系统&#xff0c;其核心是对围手术期患者信息自动采集、储存、分析并呈现。该系统通过整合围手术期中病人信息、人员信息、…

Packet Tracer – 研究 NAT 操作

Packet Tracer – 研究 NAT 操作 目标 第 1 部分&#xff1a;通过内联网研究 NAT 操作 第 2 部分&#xff1a;研究互联网中的 NAT 操作 第 3 部分&#xff1a;执行进一步研究 拓扑图 场景 帧通过网络时&#xff0c;MAC 地址可能更改。 当数据包由配置了 NAT 的设备转发时&…

转录组和蛋白组如何关联分析?先从绘制九象限图开始

转录组和蛋白组如何关联分析&#xff1f;先从绘制九象限图开始 五种常用蛋白质组学定量分析方法对比 - 知乎 (zhihu.com) 九象限图在多组学关联分析中非常重要&#xff0c;例如我们可以用九象限图展示“转录组蛋白组”、“转录组翻译组”等关联分析中不同基因的差异表达情况。…

DotNet VOL.Core框架学习使用笔记(二)(持续更新)

2023-7-5 生成代码的列表界面&#xff0c;在数据行里增加一个操作列 查看按钮&#xff0c;打开编辑框&#xff0c;然后让编辑框成为一个只读的查看界面。 页面对应的js文件中增加如下 this.columns.push 函数内容。 按钮的点击事件 重点代码 this.edit(row); 这就是框架里编…

构建工具——webpack、vite

文章目录 构建工具Webpack使用步骤配置文件&#xff08;webpack.config.js&#xff09;插件&#xff08;plugin&#xff09; ViteVite 也是前端的构建工具使用命令构建配置文件&#xff1a;vite.config.js 构建工具 当我们习惯了在 node 中编写代码的方式后&#xff0c;在回到…

page-break-after: always打印时强制分页

page-break-before 元素在指定元素前添加分页符。 <div stylepage-break-after: always;></div> <p stylepage-break-after: always;></p>https://www.runoob.com/cssref/pr-print-pagebb.html

小样本图像目标检测研究综述——张振伟论文阅读

小样本图像目标检测研究综述——张振伟&#xff08;计算机工程与应用 2022&#xff09; 论文阅读 目前&#xff0c;小样本图像目标检测方法多基于经典的俩阶段目标检测算法Faster R-CNN作为主干网络&#xff0c;当然也有将YOLO&#xff0c;SSD一阶段目标检测算法作为主干网络的…

Android Studio实现内容丰富的安卓公交线路查询平台

如需源码可以添加q-------3290510686&#xff0c;也有演示视频演示具体功能&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号084 1.开发环境 android stuido jdk1.8 eclipse mysql tomcat 开发语言&#xff1a;java 2.功能介绍 安卓端&#xff1a; …

zabbix基础3——邮箱告警

文章目录 一、环境说明二、第三方邮箱告警2.1 开启第三方邮箱SMTP服务2.2 配置用户媒介2.3 定义媒介类型2.4 配置告警方式和动作2.5 触发告警&#xff0c;测试效果 三、本地邮箱脚本3.1 服务端设置脚本3.2 设置用户媒介3.3 定义媒介类型3.4 配置告警方式动作3.4 触发告警&#…

Leetcode-每日一题【92.反转链表Ⅱ】

题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4输出&#xff1a;…

算法中的递推算法

递推算法 给定一个数的序列H0,H1,…,Hn,…若存在整数n0&#xff0c;使当n>n0时,可以用等号(或大于号、小于号)将Hn与其前面的某些项Hi(0<i<n)联系起来&#xff0c;这样的式子就叫做递推关系。 递推算法是一种简单的算法&#xff0c;即通过已知条件&#xff0c;利用特…

免费 Selenium各大浏览器驱动【谷歌chrme、火狐Firefox、IE浏览器】

aardio群 625494397 废话不多说 直接开整&#xff01; 竟然还有脸收费 服了 下载对应版本的浏览器驱动 目标网址 应用场景 Selenium库涉及到 安装selenium库 pip install selenium-i https://mirrors.aliyun.com/pypi/simple/下载对应浏览器驱动 https://registry.npmmirror.c…