1
cabing 2021-08-17 23:00:40 +08:00
rpcx
|
2
wellsc 2021-08-17 23:05:26 +08:00 via iPhone
http?
|
3
zyxk OP @wellsc #2 不是 我要做的是 c/s , 用 net 包可以,但是连接管理, 心跳包 粘包等要自己处理,想问下 TCP/IP 有没有什么框架.大家都用什么..好像用 go 做这个的少吧.
|
4
noe132 2021-08-17 23:17:27 +08:00 via Android 31
粘包警察还有 5 分钟到达战场
|
5
toma77 2021-08-17 23:19:29 +08:00
grequests
|
7
caola 2021-08-17 23:32:32 +08:00
gopacket ?
|
8
zyxk OP @cabing #1 谢谢,现在好像都是用 rpc 了? 到现在也也不是太懂 rpc,以为比传统的 tcp 通讯复杂,也没仔细看过.
刚查的,是这样吗? https://www.zhihu.com/question/41189095 |
9
lity 2021-08-17 23:34:40 +08:00
zinx
|
10
EIJAM 2021-08-17 23:35:01 +08:00 via iPhone
标准库
|
11
hedwi 2021-08-17 23:39:36 +08:00
grpc 简单高效
|
12
Mohanson 2021-08-17 23:55:20 +08:00
粘包警察虽迟但到
|
13
whwlsfb 2021-08-18 00:02:10 +08:00 via Android
grpc,既现代又高效,跨平台、工具集完备
|
16
rophie123 2021-08-18 00:40:30 +08:00 via iPhone
就用 net 库,做过一个项目,粘包没出现过
|
17
hahasong 2021-08-18 00:56:53 +08:00
TCP 哪来的粘包,建议重修网络原理
|
18
SingeeKing 2021-08-18 01:30:40 +08:00 via iPhone
@hahasong 只有 TCP 有粘包啊
|
19
SingeeKing 2021-08-18 01:32:47 +08:00 via iPhone
CS 架构其实也可以用 HTTP 的,如果需要双向通信可以 Websocket 。如果种种考虑不想选择 HTTP 的话,首选建议是 grpc,类似的替代方案也有 messagepack 或是 Go 自己的 gob 也
|
20
dcoder 2021-08-18 03:14:47 +08:00 4
TCP 哪来的粘包,建议重修网络原理 +1
|
21
Trim21 2021-08-18 04:20:32 +08:00
粘包警察虽迟但到
|
22
allenby 2021-08-18 04:35:42 +08:00 via Android 2
TCP 哪来的粘包,建议重修网络原理 +1
|
23
Microkernel 2021-08-18 06:07:26 +08:00
@SingeeKing 粘包警察又抓获一名自投罗网的
|
24
Keyes 2021-08-18 08:14:35 +08:00 via iPhone
|
25
catcn 2021-08-18 08:26:11 +08:00
|
26
leonme 2021-08-18 08:33:43 +08:00 via iPhone
流 流 流,说三遍
|
27
ICKelin 2021-08-18 08:36:10 +08:00
golang 用 net 库处理不是很麻烦吧。
|
28
chendy 2021-08-18 08:38:47 +08:00
除非 rpc 不满足需求否则就用 rpc 就好
|
29
balabalaguguji 2021-08-18 08:42:22 +08:00
|
30
qwerthhusn 2021-08-18 08:44:51 +08:00
TCP/UDP 是在第三层( TCP/IP 协议栈不是 OSI )
HTTP 是在 TCP 上面的套娃,在第四层(例外:HTTP/3 是在 UDP 上面的套娃) 你说的那些常见 RPC 协议,要么是跟 HTTP 一样直接在 TCP/UDP 的上面。要么像 GRPC 那样直接在 HTTP 上面再套 你甚至可以把 HTTP 当成一种 RPC 都没问题。 所以没有必要自己基于 TCP 自创一个 RPC 协议,直接用现成成熟的就行了,像 Thrift,gRPC 这种。 不过我建议是最最最最最简单的 HTTP 一把梭。 如果你非要自己实现,可以使用像 go-netty 或者 getty 的这种,自己定义好 codec,然后框架会帮你处理所谓的“粘包半包”问题。 |
31
BBCCBB 2021-08-18 08:45:56 +08:00
gotty
gnet 类似 netty 的框架. |
32
llbgurs 2021-08-18 08:50:11 +08:00
@balabalaguguji 不懂 TCP 才会说粘包
|
33
chenshun00 2021-08-18 08:58:41 +08:00 1
一群人不知道抓住个概念争论个什么,真的把 TCP 学明白了,用什么词汇都可以把这东西给人描述明白。粘拆又何妨,反正应用层能拿到完成的业务 package 。
|
34
dacapoday 2021-08-18 08:59:16 +08:00 2
这么多年,就一直没搞懂这些说粘包的。难道你们协议头里没有 magic code, 没有数据包 length?
|
35
mritd 2021-08-18 09:01:00 +08:00 via iPhone
drpc
|
36
yufpga 2021-08-18 09:01:50 +08:00
evio, gnet, netpoll
|
37
hasdream 2021-08-18 09:02:47 +08:00
https://pkg.go.dev/net 这个包? 类似 其他语言 socket api
|
38
raptor 2021-08-18 09:17:39 +08:00
粘包警察的工作不到位啊,都批了这么久了,还有人以为存在“粘包”这种伪概念……
你们以为的“粘包”是 TCP 的 feature,不懂说明你没学好 你们会碰到“粘包”是因为你们在 TCP 之上定义的协议有问题,说明定义这个协议的人没学好 |
39
yolee599 2021-08-18 09:20:29 +08:00 via Android
@balabalaguguji 正是因为流协议所以才没有“粘包”的说法,TCP 就像一条水管,数据是源源不断流过去的,特性就是这样。TCP 会导致“粘包”这个说法是不对的,TCP 和粘包不存在因果关系
|
40
lanlanye 2021-08-18 09:20:39 +08:00
|
41
youngce 2021-08-18 09:24:13 +08:00
gnet
|
42
balabalaguguji 2021-08-18 09:29:54 +08:00
@yolee599 #39 有点扣字眼了,当然不是说流粘,说的是你发的消息变成流传输,你的多个消息粘在一起了。
|
43
Cbdy 2021-08-18 09:30:18 +08:00 via Android
“粘包”还行
|
44
zdt3476 2021-08-18 09:42:20 +08:00
|
45
server 2021-08-18 09:42:24 +08:00
gnet
|
46
dreamage 2021-08-18 09:57:14 +08:00
建议 #17 #18 打一架
|
47
nmap 2021-08-18 10:06:23 +08:00
短短几句话就暴露了小白一个,很幼稚
|
48
leonme 2021-08-18 10:06:35 +08:00 via iPhone
@balabalaguguji 这……算了,你继续粘包吧,培训班害死人
|
49
ylsc633 2021-08-18 10:14:31 +08:00
看了评论我想学习学习(我只会 curd)
可是 你们谁也不说个原理 一方: TCP 有粘包 一方: TCP 没有粘包 那你们倒是说说啊... |
50
sunny352787 2021-08-18 10:20:33 +08:00
用 RPC 或者 websocket 吧,除了游戏已经很少看到跑裸 TCP 的了
|
51
KickAssTonight 2021-08-18 10:23:10 +08:00
|
52
abersheeran 2021-08-18 10:25:54 +08:00 10
@ylsc633 TCP 本就是流协议,没有包的概念。如果需要划分包,一定是要在上层协议里设计长度标识位来划分包和包之间的隔离线。例如 HTTP 里的 Content-Length,Socks 里的 domain-length 等等。
举个现实里的例子:TCP 协议就是一根水管,你拿着许多瓶矿泉水往管子对面输水,对你来说,水是一瓶瓶的,之间的区别很明显。但对于那边的人来说他只能收到一波又一波的水,至于这些水是属于哪一瓶的,他不知道。如果运气好,每一波水之间间隔也会很明显,但是这并不代表水管帮你把这些水分割了。运气不好的时候,水就连在一起下来了,这就是他们嘴里说的粘包。 |
54
ming159 2021-08-18 10:32:29 +08:00 2
假设有一个数据源,源源不断的产生数据,需要通过 TCP 传输,同时,这些数据是一段一段的;
假设以#开头,以$结束. 比如 #abc123$ 为一段完整数据. 应用层代码接收到数据时,就会出现如下三种情况: 1. 刚好收到完整的数据: #abc123$ 2. 分为了 2 次收到完整数据: 第一次: #abc ; 第二次: 123$ 3. 1 次收到数据,多于一段完整数据: #abc123$#ab 请问你的代码如何处理以上三种情况? onData("#abc"); onData("123$"); onData("#edf456$#hj"); onData("k789$"); 最后希望得到的是 #abc123$ #edf456$ #hjk789$ private String cache=""; public void onData(String data){ // 请把这里补充完整,就理解了. } |
55
jlkm2010 2021-08-18 10:38:12 +08:00
|
56
ming159 2021-08-18 10:49:37 +08:00 2
|
57
ckdxc 2021-08-18 10:55:39 +08:00
TCP 就是 水管出水, 你用 定量 100ml 的杯子接水, 这次接 50ml, 但是每次都接满, 你要喝的时候就喝一半, 喝多少定着杯子的刻度尺就行
|
58
goushenggege 2021-08-18 10:55:41 +08:00
双向 RPC
|
60
darknoll 2021-08-18 10:58:48 +08:00
粘包是什么鬼,拿胶水粘的吗
|
61
YuSheen1024 2021-08-18 10:59:09 +08:00
应用层出问题,非要怪到网络层( TCP )?
|
62
msaionyc 2021-08-18 11:03:33 +08:00 3
@ming159 TCP 协议里明明白白写了:面向流。它把数据以流的形式,可靠地发送给接收方,它的事情就完美地做完了。
你们提出的“粘包”概念是应用层自己该解决的,你们可以说,应用层的粘包问题,但说“TCP 的粘包问题”,是不严谨的 |
64
ming159 2021-08-18 11:04:02 +08:00
@ckdxc 你说的这是一种,我没记错,应该叫做 "定长协议" ,就是一个数据段固定长度,比如 512 个字节.每次固定取这么长度的就可以.
但是还有"可变长度"的协议,就需要在数据段中某个固定位置上指示 本次数据自身的长度,例如: #3abc,#5abcde. 表示 #开头,随后的数字表示后续数据的长度,比如 3,5,分别表示在此之后还有若干个数据才算一段完整的数据集. 还有另外一种,固定以回车换行符为分隔符的,无论多长,只要有回车换行符就切断 |
65
ZHanYao 2021-08-18 11:07:35 +08:00
这本来就是应用层的问题,你们非要往网络层扯?
我家鸡蛋孵出来了一只鸡,但是这只鸡不会飞是什么原因? 粘包警察:鸡蛋都没有翅膀,怎么可能会飞! |
66
ming159 2021-08-18 11:14:05 +08:00
“TCP 的粘包问题” 确实不严谨.这点我也承认.
"基于 TCP 传输数据,必然存在应用层数据的 粘包 /拆包问题". 如果写过 TCP 通信(Socket 编程)的懂得自然懂,不懂得说多了也没用, 可以参考 Netty 中的 LineBasedFrameDecoder : 基于回车换行符的解码器 DelimiterBasedFrameDecoder: 分隔符解码器,可以指定消息结束的分隔符 FixedLengthFrameDecoder: 固定长度解码器,它能够按照指定的长度对消息进行自动解码 LengthFieldBasedFrameDecoder :一般协议头中带有长度字段,通过使用 LengthFieldBasedFrameDecoder 传入特定的参数,来解决拆包粘包 |
67
ZHanYao 2021-08-18 11:15:04 +08:00 6
@msaionyc #62 严格来说是这样的,但是人与人沟通没必要这么抠字眼,能理解就行,就像叫人吃饭,难道就真的只吃饭不吃菜?
楼主只是想找个在应用层可以处理粘包问题的框架,并没有将“粘包问题”甩锅给 TCP 的意思,但是为什么要抓住这个点不放呢? |
68
paoqi2048 2021-08-18 11:17:16 +08:00
自己包下 net 库吧
|
71
tairan2006 2021-08-18 11:22:35 +08:00
不需要框架,直接用 net 包就行
一般用 bufio.Scanner 的 Split 就可以拆分 token 了 如果想简单点可以直接用 websocket |
72
deavorwei 2021-08-18 11:45:52 +08:00
@ming159 您好,请教下粘包的问题。TCP 有重传机制和 ACK 机制,经过 TCP 传输的数据包应该是可靠的。应用层拿到的数据包应该也是完整的、有序的,为何会出现应用层接收到数据包是不完整或者是乱序的情况。---来自没有开发经验的小学生
|
73
nowgoo 2021-08-18 12:08:26 +08:00 6
是个程序员都明白,人家问的就是应用层有没有“从字节流中拆出消息”的轮子。粘包警察纠着“粘包”两个字不放有意思吗?难道楼主不知道 TCP 是流协议,要你教?
楼主明明说了使用“粘包”和“拆包”是因为描述方便。粘包警察会因为老婆饼里没老婆跟老板打一架吗? |
75
blessingsi 2021-08-18 12:21:35 +08:00 via Android
@deavorwei 理解一下[流]协议这个说法。TCP 协议的有序性和完整性保证是针对整个流来说的,并不是代表接受端的每次 read 拿到的恰好是发送端每次 write 的内容。比如,当 TCP 一个包过大的时候,会在实际传输的时候拆开
|
76
Lemeng 2021-08-18 12:26:26 +08:00
学习学习来的,绑定一下
|
77
mxT52CRuqR6o5 2021-08-18 12:56:49 +08:00 via Android
我觉得你需要的并不是裸 TCP
|
78
Guidance3204 2021-08-18 13:45:21 +08:00
我前几天正好写了一个序列化,反序列化消息到 struct 的库 https://github.com/lai323/bytecodec
|
80
Frytea 2021-08-18 14:16:52 +08:00
ZeroMQ? 之前做 C 开发经常用
|
81
maplelin 2021-08-18 14:25:16 +08:00
@deavorwei #72 很简单的举例,水管漏了,中间有一部分数据丢掉了。但是不代表后面的数据就不能正确到达目的地。有序只是接受端和发送端会按照顺序发送数据和接受数据,并不代表每次都会等到收到接受端前一个数据已收到的状态码才发送下一段数据,这样效率是很低下的。
|
82
Michaelssss 2021-08-18 14:25:24 +08:00
你要写裸 TCP ?首先就是先定义 Frame 或者 Protocol,然后基于上述将 Payload 用于业务=。=详情见 HTTP 是怎么做的。。。一个意思
|
83
ming159 2021-08-18 14:30:48 +08:00
@darknoll 54 楼 并不是虚构的协议. 可以参考
1. Modbus ASCII 在 ASCII 传输模式下,消息帧以英文冒号”:”( 3A )开始,以回车( 0D )和换行( 0A )结束. 2. 基恩士 PLC 中的 上位链路协议: [功能码] 开始,回车( 0D )结束. |
84
dbpe 2021-08-18 14:41:54 +08:00
哈哈哈....笑死
谁知道 http1.1 的长链接是怎么做的呢... 斜眼笑 |
85
ming159 2021-08-18 14:44:13 +08:00
@deavorwei
TCP 保证了 有序性,完整性. 是指: 发送端 发送了 #1 2 3 4 5$ #a b c d e$ . 接收端最终收到的也是 #1 2 3 4 5$ #a b c d e$ 有序,且完整. 但是 接收过程 接收过程 接收过程 (重要的点) 会是这样的 情况 1: #1 2 3 4 5$ #a b c d e$ 情况 2: #1 2 3 和 4 5$ #a b c d e$ 顺序没乱,且数据没丢. |
86
jsq2627 2021-08-18 14:50:18 +08:00
23333 当看到 LZ 写了“粘包”两字就猜到帖子的走向了。
|
87
wengang285 2021-08-18 14:55:04 +08:00 1
@ming159 长度( 4 字节)+buffer,缓冲区可读,那么查看先读长度,然后根据长度往后取 buffer,长度不够这次就不取,等待底层( epoll )的再次通知
|
88
ace12 2021-08-18 14:58:39 +08:00 via Android
看到粘包,我就兴奋了哈哈哈
|
89
SillyChenBrother 2021-08-18 15:02:53 +08:00 3
TCP 没有所谓的粘包说法
网络层,IP 数据报帮你分报,在这里会切块 传输层,TCP 帮你分块,这里也会分块,但 UDP 就不会分 TCP 传过来,你通过程序收到的数据肯定是不会破损的,都三次握手四次放手,拥塞控制,失败重传,流水线运输,传过来就都是对的数据。 数据是一个流,过来的一个个报文,也就是所谓的包,你要自己处理数据边界,也就是说你自己定义的应用层协议必须处理如何区分边界的问题,比如发现开头是 Xx 就是你的一个切确的文本的开始,或者叫结构体的开始,直到 yyy 就是文本的结束,以此反复,也就是解码和编码的问题,也就是说这已经不是传输层的问题了,这是应用层了,参考 http,ftp 等协议,gRPC/thrift 这种序列化解编码就是你文中描述所需要用到,所以粘包的描述是多年来的玄之又玄的说法,每次听起来一头雾水,然后面试官还喜欢装逼问这个。 设计好解编码二进制的序列化应用层协议,就没有所谓的粘包,拆包,朦朦胧胧,龙龙萌萌 |
90
ming159 2021-08-18 15:04:32 +08:00
@wengang285
但也可以是 长度( 4 字节)+buffer,缓冲区可读,那么查看先读长度,然后根据长度往后取 buffer,有多少取多少,因为没有取够, 那么下一次再次通知的时候,与上一次的已经取出来的拼接,直到取够 "长度" 为一次完整帧. |
91
tonyan93 2021-08-18 15:04:46 +08:00
粘包并不是 TCP 协议造成的,它的出现是因为应用层协议设计者对 TCP 协议的错误理解,忽略了 TCP 协议的定义并且缺乏设计应用层协议的经验。
|
92
JoeBreeze 2021-08-18 15:11:31 +08:00
TCP: 你们在说啥?
|
93
lesismal 2021-08-18 15:13:22 +08:00
足够满足楼主和各位各种业务场景:
https://github.com/lesismal/arpc |
94
lesismal 2021-08-18 15:14:49 +08:00
@abersheeran 没办法,"粘包" 虽然是错误的概念,但已约定俗成,懂的人只是用这个词沟通问题
|
95
D3EP 2021-08-18 15:17:23 +08:00
Golang 这种阻塞 IO 模型还要什么框架..
|
96
wengang285 2021-08-18 15:35:03 +08:00
@ming159 也可以,但是这样会导致解码的逻辑多处理一个分支,增加代码的复杂性,但是并没有带来性能的提升,实际工程中不会这么写
|
97
ming159 2021-08-18 15:49:00 +08:00
@wengang285 根据实际场景选择吧,例如 数据量相对较大,且 buffer 小的时候,如果不尽快从 buffer 中取出数据, 引发 流量控制机制,反而导致整体传输变慢.
|
99
xuanbg 2021-08-18 16:04:14 +08:00
老老实实用一个 http 之类的应用层协议,而不是把 TCP 协议当应用层协议用,哪来的粘包。
|
100
lesismal 2021-08-18 16:04:47 +08:00
介绍下自己俩库,arpc 和 nbio:
https://www.v2ex.com/t/794435#reply0 这两个库可以覆盖绝大多数应用业务场景,比如:RPC 、IM 、游戏、广播 /推送服务、其他自家功能交互等。 支持 tcp/kcp/quic/websocket 各种协议作为传输载体。 单机连接数量不特别大比如 10k-100k 这种级别的(普通人眼里觉得 10k 已经算大了,但是对于网络框架而言,这个量级很小,那些性能差的脚本语言就不要来讨论性能了),配置能扛得住就默认标准库方案。 海量并发比如单机 100k-1000k 这种级别的,可以 arpc+nbio,照样能扛。 这个领域里,一是性能,二是易用性,有兴趣的同学可以自行对比。 关于性能,有兴趣的同学可以去看下鸟窝老师和字节同学的 benchmark 库,硬件不同压测结果可能存在差异,所以有兴趣的同学不要看仓库文档展示的结果,请自己机器实测看效果: github.com/rpcxio/rpcx-benchmark github.com\cloudwego\kitex-benchmark |