Golang 解决TCP“粘包“问题 TCP 协议是面向连接,可靠的流式协议,当 Server 去 Read 的时候 , 每次读到的数据都不一定是完整的 , 该方法会返回读到的字节数,因此,当我们写 Server 的时候,什么时候去回调用户设置的 callback ?也就是怎么样保证每次都能拿到一个完整的包数据,这个就是”粘包“问题的由来 。
传统的 , 有两种方法解决 。一是分隔符协议,即每条消息结尾设置固定分隔符,Server 读到分隔符就认为读到了完整的包数据;二是长度协议,即在每个消息头部设置固定长度的字段 , 表征消息长度,再往后读取该长度的消息即可 。
目前长度协议用的较多,因为分隔符协议需要 Server 不停的检测 , 很耗费性能 。长度协议实现中比较重要的点是头部的长度以及字节序,2个字节可表示2^16-1个字节的内容,如果不够 , 那就上4字节,字节序相关的只是可以参考: ”字节序“是什么鬼?
先来个没处理粘包的:
common/server.go:
测试一下:
因为每次只读5个字节,可以明显看到消息”乱了“,但就算把这个值增大,你只要是设置了,就会存在这个问题 。
delimeter/server.go:
还是拿上个测试脚本跑,结果:
这次看到每个消息长度不一样,但是都是”完整的“ 。
length/server.go:
client 也得相应调整:
测试结果:
效果跟分隔符协议一样,都可以解决”粘包“问题 。
只要是 TCP 协议,任何语言都需要处理 ”粘包“ 问题,我们用 PHP 写一个客户端测试一下:
完美!
只有在直接使用 TCP 协议才存在 "粘包" 问题,其上层应用层协议比如 HTTP ,已经帮我们处理好了,无需关注这些底层,但是我们自己实现一个自定义协议,就必须考虑这些细节了 。
2021-03-08
在 Go 中实现一个支持并发的 TCP 服务端TCP 和 UDP 服务端随处可见,它们基于 TCP/IP 协议栈,通过网络为客户端提供服务 。在这篇文章中,我将介绍如何使用 Go 语言开发一个用于返回随机数、支持并发的 TCP 服务端 。对于每一个来自 TCP 客户端的连接,它都会启动一个新的 goroutine(轻量级线程)来处理相应的请求 。
你可以在 GitHub 上找到本项目的源码:concTcp.go 。
这个程序的主要逻辑在handleConnection 函数中,具体实现如下:
在main 函数的实现部分,每当 TCP 服务端收到 TCP 客户端的连接请求,它都会启动一个新的 goroutine 来为这个请求提供服务 。
首先,main 确保程序至少有一个命令行参数 。注意,现有代码并没有检查这个参数是否为有效的 TCP 端口号 。不过,如果它是一个无效的 TCP 端口号,net.Listen 就会调用失败,并返回一个错误信息,类似下面这样:
net.Listen 函数用于告诉 Go 接受网络连接 , 因而承担了服务端的角色 。它的返回值类型是 net.Conn,后者实现了 io.Reader 和 io.Writer 接口 。此外, main 函数中还调用了 rand.Seed 函数,用于初始化随机数生成器 。最后 , for 循环允许程序一直使用 Accept 函数来接受 TCP 客户端的连接请求,并以 goroutine 的方式来运行 handleConnection(c) 函数,处理客户端的后续请求 。
net.Listen 函数的第一个参数定义了使用的网络类型,而第二个参数定义了服务端监听的地址和端口号 。第一个参数的有效值为 tcp 、 tcp4 、 tcp6 、 udp 、 udp4 、 udp6 、 ip 、 ip4 、 ip6 、 Unix (Unix 套接字)、 Unixgram 和 Unixpacket,其中: tcp4 、 udp4 和 ip4 只接受 IPv4 地址,而 tcp6 、 udp6 和 ip6 只接受 IPv6 地址 。
concTCP.go 需要一个命令行参数,来指定监听的端口号 。当它开始服务 TCP 客户端时 , 你会得到类似下面的输出:
netstat 的输出可以确认 congTCP.go 正在为多个 TCP 客户端提供服务,并且仍在继续监听建立连接的请求:
在上面输出中,最后一行显示了有一个进程正在监听 8001 端口,这意味着你可以继续连接 TCP 的 8001 端口 。第一行和第二行显示了有一个已建立的 TCP 网络连接,它占用了 8001 和 62556 端口 。相似地 , 第三行和第四行显示了有另一个已建立的 TCP 连接,它占用了 8001 和 62554 端口 。
下面这张图片显示了concTCP.go 在服务多个 TCP 客户端时的输出:
类似地 , 下面这张图片显示了两个 TCP 客户端的输出(使用了nc 工具):
【包含go语言实现tcp的词条】 你可以在 维基百科上找到更多关于 nc (即 netcat )的信息 。
现在,你学会了如何用大约 65 行 Go 代码来开发一个生成随机数、支持并发的 TCP 服务端 , 这真是太棒了!如果你想要让你的 TCP 服务端执行别的任务,只需要修改handleConnection 函数即可 。
via:
作者:Mihalis Tsoukalos选题:lkxed译者:lkxed校对:wxy
go语言TCP连接池rocket049/connpool使用安装:
go get -v -u github.com/rocket049/connpool
go get -v -u gitee.com/rocket049/connpool
rocket049/connpool 包是本人用go语言开发的,提供一个通用的TCP连接池,初始化参数包括最高连接数、超时秒数、连接函数,放回连接池的连接被重新取出时 , 如果已经超时,将会自动重新连接;如果没有超时,连接将被复用 。
可调用的函数:
调用示例:
关于go语言实现tcp和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。
推荐阅读
- 直播间人物特效素材,直播特效模板
- 音响sap是什么意思,音箱spl是什么意思
- 华为服务器品牌有哪些服务,华为服务器品牌有哪些服务项目
- pdf文档转excel,pdf文档转换
- vb.netbs源码 vbnet com
- 怎么选择手机上网卡路由器,手机用路由器上网卡怎么设置
- 2550装什么cpu,2550k最高带什么显卡
- 阿义直播素材,虎牙阿泰直播素材
- 管道函数python. 管道函数必须具有支持的集合返回类型