单机轻松支持百万并发的go协程的简单tcpsocket服务端客户端通信小程序示例源码

单机轻松支持百万并发的go协程的简单tcpsocket服务端客户端通信小程序示例源码

服务端 server.go

package mainimport ("bufio""fmt""io""net""os""strings""time"
)// 简单的客户端服务端通信示例
// 知识点总结:
// 1.listener.Accept() 这个会一直等待客户端链接, 有一个链接就往后面执行代码没有链接就阻塞;
// 2. go process(conn) 会对每个链接开启一个协程进行处理
// 3. 在协程处理函数里面必须要在开头加上 defer conn.Close() 确保协程结束后关闭相应的链接资源
// 4. 从终端获取用户输入数据使用了os.Stdin作为输入源 reader := bufio.NewReader(os.Stdin)
// 5. 输入源在每次读取完毕后可以重置 reader.Reset(os.Stdin) // 每次数据发送后重置reader
// 在从conn.Read(buf)读取数据显示时需要带上这里读取到的n 如:string(buf[:n])
func main() {listener, err := net.Listen("tcp", ":8008")if err != nil {fmt.Println("链接异常:", err)}defer listener.Close() //关闭链接// 循环,等待客户端来链接for {conn, err := listener.Accept() // 等待链接if err != nil {fmt.Println("Listener.Accept:", err)continue // 跳转到下一个链接}go process(conn)}
}// 处理链接函数
func process(conn net.Conn) {defer conn.Close() //这个处理进程退出后确保关闭链接connfmt.Printf("收到来自%v的链接\n", conn.RemoteAddr())//向客户端发送一条消息conn.Write([]byte("Welcome to Go tcp server!"))chExit := make(chan int, 2) // 创建一个退出管道go sendMsFromStdin(conn, chExit)go readMsgFromClient(conn, chExit)//阻塞等待用户输入for {n, ok := <-chExitif n == 1 {fmt.Printf("客户端 %v 链接已关闭\n", conn.RemoteAddr())return} else {fmt.Printf("main管道 n=%v ok=%v \n", n, ok)break}}}
func readMsgFromClient(conn net.Conn, ch chan int) {for {// 每次循环都新创建一个切片用于读取客户端发送的数据buf := make([]byte, 1024)n, err := conn.Read(buf) // 这个Read会使协程一直阻塞在这里,直到客户端发送消息if err == nil && n > 0 {// string(buf[:n]) 这里的n很重要,代表仅显示从conn中读取到的信息fmt.Printf("收到数据:%v", string(buf[:n]))} else if err == io.EOF {//fmt.Printf("错误退出:n=%v,  %v", n, err)ch <- 1break //退出} else if _, ok := <-ch; !ok {//fmt.Print("client closed!!")return //管道已经关闭,直接退出} else {fmt.Printf("等待客户端%v发送消息", conn.RemoteAddr())}}close(ch) //关闭ch
}// 从终端获取数据并发送到客户端
func sendMsFromStdin(conn net.Conn, ch chan int) {// 这里使用标准输入作为rd, os.Stdinreader := bufio.NewReader(os.Stdin)maxErrCnt := 3 // 最多重试次数,超过这个次数这个链接就会直接关闭//循环处理for {// 从终端读取用户的输入并发送给服务器line, err := reader.ReadString('\n')if err != nil {fmt.Printf("获取数据失败, %v", err)}if strings.HasPrefix(line, "quit") {fmt.Printf("服务端强制关闭了客户端 %v\n", conn.RemoteAddr())ch <- 1 //写入1 退出循环break}// 读取数据正常,开始发送数据len, err := conn.Write([]byte(line))if err != nil && maxErrCnt > 0 {maxErrCnt--fmt.Printf("发送数据错误 %v 等待3秒后重试,还剩 %d次重试机会\n", err, maxErrCnt)time.Sleep(3 * time.Second)} else if err == nil {fmt.Printf("本次发送了 %v 个字节的数据\n", len)reader.Reset(os.Stdin) // 每次数据发送后重置reader} else if maxErrCnt < 0 {ch <- 1 //写入1 退出循环break} else if _, ok := <-ch; !ok { // 因为这个管道有2个地方可以关闭, 所以加这个判断确保管道关闭后可以正确及时退出本函数return //管道已经关闭,直接退出}}close(ch) //关闭ch}

客户端 client.go

package mainimport ("bufio""fmt""io""net""os""strings""time"
)func main() {conn, err := net.Dial("tcp", "127.0.0.1:8008")if err != nil {fmt.Println("链接失败: ", err)return}defer conn.Close()chExit := make(chan int, 1)// 从终端获取数据并发送到服务端go sendMsFromStdin(conn, chExit)go readMsgFromServer(conn)//阻塞等待用户输入for {n, ok := <-chExitif n == 1 {fmt.Println("用户退出客户端!")break} else {fmt.Printf("main管道 n=%v ok=%v \n", n, ok)}}fmt.Println("client exit")
}
func readMsgFromServer(conn net.Conn) {for {buf := make([]byte, 1024)n, err := conn.Read(buf)if err == io.EOF {break} else if err == nil && len(buf[:n]) > 0 {fmt.Printf("接收到服务端的信息: %v\n", string(buf[:n]))}}
}// 从终端获取数据并发送到服务端
func sendMsFromStdin(conn net.Conn, ch chan<- int) {// 这里使用标准输入作为rd, os.Stdinreader := bufio.NewReader(os.Stdin)maxErrCnt := 3//循环处理for {// 从终端读取用户的输入并发送给服务器line, err := reader.ReadString('\n')if err != nil {fmt.Printf("获取数据失败, %v", err)}if strings.HasPrefix(line, "quit") {ch <- 1 //写入1 退出循环break}// 读取数据正常,开始发送数据len, err := conn.Write([]byte(line))if err != nil && maxErrCnt > 0 {maxErrCnt--fmt.Printf("发送数据错误 %v 等待3秒后重试,还剩 %d次重试机会\n", err, maxErrCnt)time.Sleep(3 * time.Second)} else if err == nil {fmt.Printf("本次发送了 %v 个字节的数据\n", len)reader.Reset(os.Stdin) // 每次数据发送后重置reader} else if maxErrCnt <= 0 {ch <- 1 //写入1 退出循环break} else {fmt.Printf("else len:%v  err:%v \n", len, err)}}fmt.Println("即将关闭ch")close(ch) //关闭ch}

tcpSocket客户端服务端通信示例小程序演示视频-CSDN直播

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

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

相关文章

管理学SCI期刊,中科院4区,审稿快易录用,性价比超高!

一、期刊名称 Central European Journal of Operations Research 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;管理学 影响因子&#xff1a;1.7 中科院分区&#xff1a;4区 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;选择开放出版需…

人大金仓报The connection attempt failed.Reason:Connection reset解决办法

在连接人大京仓数据库 的时候报下面的错误 解决办法&#xff1a; 更换这里的IP地址就行&#xff0c;不要用127.0.0.1&#xff0c;然后就可以了

24.c++异常(异常的抛出和捕获、异常的重新抛出、抛出异常对象、抛出派生类对象、异常规范)

1.C语言传统的处理错误的方式 传统的错误处理机制&#xff1a; 终止程序&#xff0c;如assert&#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&#xff0c;除0错误时就会终止程序。返回错误码&#xff0c;缺陷&#xff1a;需要程序员自己去查找对应的错误。如系统…

qq空间:图片批量下载js脚本工具,javascript批量下载图片

qq空间&#xff1a;图片批量下载js脚本工具&#xff0c;javascript批量下载图片 QQ空间很多老照片想下载&#xff0c;但是腾讯没放开&#xff0c;只能一张张下载太麻烦。用前端js写了一个脚本支持批量下载。另外就是空间内的照片会被压缩&#xff0c;过几年再看&#xff0c;个…

vscode的git插件使用教程

虽然git的命令我没有滚瓜烂熟&#xff0c;但vscode的git插件是尊嘟很好用啊&#xff0c;都被我用烂了。在网上看见一个讲的很不错的插件教程。借鉴一下。并在一些地方用块引用进行了补充说明&#xff01; 跳过了vscode安装过程。 克隆GitHub中的存储库&#xff1a; 1、复制Gi…

Redmine 的主题 bs-redmine-theme-dark 完善

Redmine 的主题 bs-redmine-theme-dark 感觉还不错, 但是有部分样式看起来不是很舒服, 以下是一些调整: bs-redmine-theme-dark/stylesheets/application.css import url(../../../stylesheets/application.css); import url(style.css); import url(plugins.css); import url…

自然资源-重大建设项目前期的主要工作流程和重点关注事项

自然资源-重大建设项目前期的主要工作流程和重点关注事项 重大建设项目通常是指对国家、地区或组织具有重要战略意义&#xff0c;涉及大规模投资和长期发展的项目。这些项目往往对经济、社会和环境产生深远影响&#xff0c;通常涉及基础设施、科技、能源、交通、水利等领域。 …

解码器中DPB的作用是什么

在解码器中&#xff0c;DPB&#xff08;Decoded Picture Buffer&#xff0c;即解码图片缓存区&#xff09;的作用是存储解码过程中的参考帧。这些参考帧被用于运动补偿&#xff0c;这是预测编码中的关键步骤&#xff0c;可以显著提高视频压缩效率。 DPB确保了编码器和解码器在…

ai智能机器人电销的发展现状如何?

在移动互联网时代&#xff0c;人们对于营销的需求越来越高&#xff0c;而传统的营销方式已经无法满足人们的需求。下面我们来看看智能机器人电销的发展现状如何&#xff1f; 智能机器人电销作为一种全新的营销方式&#xff0c;正在迅速崛起。据市场机构统计&#xff0c;未来几…

C语言中的关键字static和extern

Hello,亲爱的小伙伴们&#xff0c;我又来了&#xff0c;上一期作者菌讲解了C语言中函数的知识点&#xff0c;得到了很好的反馈&#xff0c;这里作者菌感谢每一个至此我的小伙伴&#xff01;&#xff01;今天作者菌又来补充一些很有用的知识&#xff0c;感兴趣的uu们不要吝啬手中…

HTML学习|网页基本信息、网页基本标签、图像标签、超链接标签、列表标签、表格标签、媒体元素、页面结构分析、iframe内联框架

网页基本信息 DOCTYPE是设置使用什么规范&#xff0c;网页整个信息都在html标签中&#xff0c;head标签里包含字符集设置&#xff0c;网页介绍等信息&#xff0c;title标签是网页的名称&#xff0c;网页的主干都在body标签中 网页基本标签 标题标签 h1~h6都是标题标签&#x…

UE进阶篇四:多语言本地化

多语言 1、创建字符串表格&#xff1a;可以通过导入/导出CSV文件编辑或者编辑器直接编辑 2、工具 -> 本地化控制板 收集引擎中文本 3、添加新语言, 导出 .po文件&#xff0c;文本编辑也可直接编辑器编辑 4、使用方法 4.1 FText直接添加本地化 4.2 蓝图调用 4.3 C调用 5、…

鸿蒙开发-ArkTS语言-容器-非线性容器

鸿蒙开发-UI-web 鸿蒙开发-UI-web-页面 鸿蒙开发-ArkTS语言-基础类库 鸿蒙开发-ArkTS语言-并发 鸿蒙开发-ArkTS语言-并发-案例 鸿蒙开发-ArkTS语言-容器 文章目录 前言 一、非线性容器 1.HashMap 2.HashSet 3.TreeMap 4.TreeSet 5.LightWeightMap 6.LightWeightSet 7.P…

(一)Linux的vim编辑器的使用

一.vim编辑器 Vim 是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。简单的来说, vi 是老式的字处理器,不过功能已经很齐全了,但是还是有可以进步的地方。 vim 则可以说是程序开发者的一项很好用的工具。 二…

活动倒计时!四城再度联动,盘古信息与您相约上海|重庆|东莞|合肥

五月&#xff0c;是生命的复苏季&#xff0c;是希望的播种月。在这个充满活力的时节&#xff0c;盘古信息将在上海、重庆、东莞、合肥四地盛大举办四场精彩纷呈的活动。届时&#xff0c;我们将呈现一系列精心打造的工业软件产品及解决方案&#xff0c;带您领略制造业数字化转型…

设计模式概览说明

Java 中常见的设计模式有很多种。以下是其中一些主要的设计模式&#xff0c;共23种&#xff1a; 1、创建型模式&#xff08;Creational Patterns&#xff09;&#xff08;5种&#xff09; 工厂方法模式&#xff08;Factory Method Pattern&#xff09; 抽象工厂模式&#xff08…

深入入IAEA底层LinkedList

✅作者简介&#xff1a;大家好&#xff0c;我是再无B&#xff5e;U&#xff5e;G&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;再无B&#xff5e;U&#xff5e;G-CSDN博客 目标&#xff1a; 1.掌握LinkedList 2.…

ESG榜单冲击数据集(2000-2022年)

参照《财经研究》中刘柏&#xff08;2024&#xff09;的做法&#xff0c;以2015年为中点&#xff0c;根据商道荣绿2015年6月公开的ESG榜单数据&#xff0c;构建ESG榜单冲击的DID数据&#xff0c;如果公司属于ESG榜单冲击的公司&#xff0c;且年份≥2015&#xff0c;则为1&#…

母婴店运用商城小程序店铺的效果是什么

母婴市场规模高&#xff0c;还可与不少行业无缝衔接&#xff0c;尤其是以90后、00后为主的年轻人&#xff0c;在备孕生育和婴儿护理前后等整体流程往往不惜重金且时间长&#xff0c;母婴用品无疑是必需品&#xff0c;商家需要多方面拓展全面的客户及打通场景随时消费路径。 运…

centos下重启redis

磁盘满了&#xff0c;发现连接不上redis了&#xff0c;我们重启一下 // 先查看下redis进程号&#xff0c;得到是8677 ps -ef | grep redis root 2642 31692 0 16:50 pts/5 00:00:00 grep --colorauto redis root 8677 1 0 4月25 ? 00:09:47 ./src/r…