V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
beego
zyxk
V2EX  ›  Go 编程语言

golang 有什么 TCP 框架?

  •  
  •   zyxk · 102 天前 · 8919 次点击
    这是一个创建于 102 天前的主题,其中的信息可能已经有所发展或是发生改变。
    可以管理连接, 心跳包 处理粘包等,
    web 方面的很多, tcp 的没找到,大家做 TCP 都用什么呢?
    第 1 条附言  ·  101 天前
    我要做的是 c/s , 用 net 包可以,但是连接管理, 心跳包 粘包等要自己处理,
    想问下 TCP/IP 有没有什么框架.大家都用什么..好像用 go 做这个的少吧.
    好像现在都是用 rpc 实现? 新学 golang , 没找到合适的 tcp 框架.做 client/server ,用 rpc 合适?
    第 2 条附言  ·  101 天前
    谢谢各位的回复.

    tcp 是数据流, 如果 client 连续发送消息, tcp 可能会将几个连续发送出去的请求合并成一个请求发出去,
    server 收到合并后的一个请求. 这个时候,一般就需要自己处理消息边界问题.
    使用原生 TCP 那就一定会遇到数据的粘和分这个问题吧,

    我觉得粘包和拆包的描述还是挺形象的,不然怎么形容这个现象呢.
    第 3 条附言  ·  101 天前
    我只是觉的用 golang 自带 net 包中的 tcp ,有一点点麻(tou)烦(lan),所以想找个相关的框架.

    麻烦大家别再纠结粘包了.
    116 条回复    2021-08-20 12:42:52 +08:00
    1  2  
    cabing
        1
    cabing   102 天前
    rpcx
    wellsc
        2
    wellsc   102 天前 via iPhone
    http?
    zyxk
        3
    zyxk   102 天前
    @wellsc #2 不是 我要做的是 c/s , 用 net 包可以,但是连接管理, 心跳包 粘包等要自己处理,想问下 TCP/IP 有没有什么框架.大家都用什么..好像用 go 做这个的少吧.
    noe132
        4
    noe132   102 天前 via Android   ❤️ 30
    粘包警察还有 5 分钟到达战场
    toma77
        5
    toma77   102 天前
    grequests
    zyxk
        6
    zyxk   102 天前
    @noe132 #4 小白听不懂啊.

    @toma77 #5 这个是 http 库吧.
    caola
        7
    caola   101 天前
    gopacket ?
    zyxk
        8
    zyxk   101 天前
    @cabing #1 谢谢,现在好像都是用 rpc 了? 到现在也也不是太懂 rpc,以为比传统的 tcp 通讯复杂,也没仔细看过.
    刚查的,是这样吗? https://www.zhihu.com/question/41189095
    lity
        9
    lity   101 天前
    zinx
    EIJAM
        10
    EIJAM   101 天前 via iPhone
    标准库
    hedwi
        11
    hedwi   101 天前
    grpc 简单高效
    Mohanson
        12
    Mohanson   101 天前
    粘包警察虽迟但到
    whwlsfb
        13
    whwlsfb   101 天前 via Android
    grpc,既现代又高效,跨平台、工具集完备
    zyxk
        14
    zyxk   101 天前
    @Mohanson #12 粘包警察虽迟但到 啥意思啊, 虽迟但到懂. 粘包警察不懂啥意思.
    lasfresas
        15
    lasfresas   101 天前 via Android
    @zyxk 就是有人喜欢说 tcp 黏包之类的话
    rophie123
        16
    rophie123   101 天前 via iPhone
    就用 net 库,做过一个项目,粘包没出现过
    hahasong
        17
    hahasong   101 天前
    TCP 哪来的粘包,建议重修网络原理
    SingeeKing
        18
    SingeeKing   101 天前 via iPhone
    @hahasong 只有 TCP 有粘包啊
    SingeeKing
        19
    SingeeKing   101 天前 via iPhone
    CS 架构其实也可以用 HTTP 的,如果需要双向通信可以 Websocket 。如果种种考虑不想选择 HTTP 的话,首选建议是 grpc,类似的替代方案也有 messagepack 或是 Go 自己的 gob 也
    dcoder
        20
    dcoder   101 天前   ❤️ 4
    TCP 哪来的粘包,建议重修网络原理 +1
    Trim21
        21
    Trim21   101 天前
    粘包警察虽迟但到
    allenby
        22
    allenby   101 天前 via Android   ❤️ 2
    TCP 哪来的粘包,建议重修网络原理 +1
    Microkernel
        23
    Microkernel   101 天前
    @SingeeKing 粘包警察又抓获一名自投罗网的
    catcn
        25
    catcn   101 天前
    leonme
        26
    leonme   101 天前 via iPhone
    流 流 流,说三遍
    ICKelin
        27
    ICKelin   101 天前
    golang 用 net 库处理不是很麻烦吧。
    chendy
        28
    chendy   101 天前
    除非 rpc 不满足需求否则就用 rpc 就好
    balabalaguguji
        29
    balabalaguguji   101 天前
    @leonme
    @allenby
    @dcoder
    @hahasong

    你们是没用过 TCP 吧,就是因为流,才需要处理粘包、分包问题,不懂不要乱喷,好好补补知识
    qwerthhusn
        30
    qwerthhusn   101 天前
    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,然后框架会帮你处理所谓的“粘包半包”问题。
    BBCCBB
        31
    BBCCBB   101 天前
    gotty
    gnet

    类似 netty 的框架.
    llbgurs
        32
    llbgurs   101 天前
    @balabalaguguji 不懂 TCP 才会说粘包
    chenshun00
        33
    chenshun00   101 天前   ❤️ 1
    一群人不知道抓住个概念争论个什么,真的把 TCP 学明白了,用什么词汇都可以把这东西给人描述明白。粘拆又何妨,反正应用层能拿到完成的业务 package 。
    dacapoday
        34
    dacapoday   101 天前   ❤️ 2
    这么多年,就一直没搞懂这些说粘包的。难道你们协议头里没有 magic code, 没有数据包 length?
    mritd
        35
    mritd   101 天前 via iPhone
    drpc
    yufpga
        36
    yufpga   101 天前
    evio, gnet, netpoll
    hasdream
        37
    hasdream   101 天前
    https://pkg.go.dev/net 这个包? 类似 其他语言 socket api
    raptor
        38
    raptor   101 天前
    粘包警察的工作不到位啊,都批了这么久了,还有人以为存在“粘包”这种伪概念……

    你们以为的“粘包”是 TCP 的 feature,不懂说明你没学好

    你们会碰到“粘包”是因为你们在 TCP 之上定义的协议有问题,说明定义这个协议的人没学好
    yolee599
        39
    yolee599   101 天前 via Android
    @balabalaguguji 正是因为流协议所以才没有“粘包”的说法,TCP 就像一条水管,数据是源源不断流过去的,特性就是这样。TCP 会导致“粘包”这个说法是不对的,TCP 和粘包不存在因果关系
    lanlanye
        40
    lanlanye   101 天前
    youngce
        41
    youngce   101 天前
    gnet
    balabalaguguji
        42
    balabalaguguji   101 天前
    @yolee599 #39 有点扣字眼了,当然不是说流粘,说的是你发的消息变成流传输,你的多个消息粘在一起了。
    Cbdy
        43
    Cbdy   101 天前 via Android
    “粘包”还行
    zdt3476
        44
    zdt3476   101 天前
    server
        45
    server   101 天前
    gnet
    dreamage
        46
    dreamage   101 天前
    建议 #17 #18 打一架
    nmap
        47
    nmap   101 天前
    短短几句话就暴露了小白一个,很幼稚
    leonme
        48
    leonme   101 天前 via iPhone
    @balabalaguguji 这……算了,你继续粘包吧,培训班害死人
    ylsc633
        49
    ylsc633   101 天前
    看了评论我想学习学习(我只会 curd)

    可是 你们谁也不说个原理

    一方: TCP 有粘包
    一方: TCP 没有粘包

    那你们倒是说说啊...
    sunny352787
        50
    sunny352787   101 天前
    用 RPC 或者 websocket 吧,除了游戏已经很少看到跑裸 TCP 的了
    abersheeran
        52
    abersheeran   101 天前   ❤️ 10
    @ylsc633 TCP 本就是流协议,没有包的概念。如果需要划分包,一定是要在上层协议里设计长度标识位来划分包和包之间的隔离线。例如 HTTP 里的 Content-Length,Socks 里的 domain-length 等等。

    举个现实里的例子:TCP 协议就是一根水管,你拿着许多瓶矿泉水往管子对面输水,对你来说,水是一瓶瓶的,之间的区别很明显。但对于那边的人来说他只能收到一波又一波的水,至于这些水是属于哪一瓶的,他不知道。如果运气好,每一波水之间间隔也会很明显,但是这并不代表水管帮你把这些水分割了。运气不好的时候,水就连在一起下来了,这就是他们嘴里说的粘包。
    402159806
        53
    402159806   101 天前
    @ylsc633 TCP 本身协议不存在粘包说法, 数据传输中的粘包是自定协议没有定义好
    ming159
        54
    ming159   101 天前   ❤️ 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){
    // 请把这里补充完整,就理解了.
    }
    ming159
        56
    ming159   101 天前   ❤️ 2
    @leonme
    @raptor
    @allenby
    @dcoder
    @hahasong
    @lasfresas
    "Talk is cheap ,Show me the code"
    请贴出你们针对 54 楼问题的代码
    ckdxc
        57
    ckdxc   101 天前
    TCP 就是 水管出水, 你用 定量 100ml 的杯子接水, 这次接 50ml, 但是每次都接满, 你要喝的时候就喝一半, 喝多少定着杯子的刻度尺就行
    goushenggege
        58
    goushenggege   101 天前
    双向 RPC
    zyxk
        59
    zyxk   101 天前
    @jlkm2010 #55 谢谢,早就发现这个 gnet 了,这个库没有发现 demo,不知道为啥.
    darknoll
        60
    darknoll   101 天前
    粘包是什么鬼,拿胶水粘的吗
    YuSheen1024
        61
    YuSheen1024   101 天前
    应用层出问题,非要怪到网络层( TCP )?
    msaionyc
        62
    msaionyc   101 天前   ❤️ 3
    @ming159 TCP 协议里明明白白写了:面向流。它把数据以流的形式,可靠地发送给接收方,它的事情就完美地做完了。
    你们提出的“粘包”概念是应用层自己该解决的,你们可以说,应用层的粘包问题,但说“TCP 的粘包问题”,是不严谨的
    darknoll
        63
    darknoll   101 天前
    @ming159 你不能直接发数据啊,你得在前面加上协议 magic number+数据长度
    ming159
        64
    ming159   101 天前
    @ckdxc 你说的这是一种,我没记错,应该叫做 "定长协议" ,就是一个数据段固定长度,比如 512 个字节.每次固定取这么长度的就可以.
    但是还有"可变长度"的协议,就需要在数据段中某个固定位置上指示 本次数据自身的长度,例如: #3abc,#5abcde.
    表示 #开头,随后的数字表示后续数据的长度,比如 3,5,分别表示在此之后还有若干个数据才算一段完整的数据集.

    还有另外一种,固定以回车换行符为分隔符的,无论多长,只要有回车换行符就切断
    ZHanYao
        65
    ZHanYao   101 天前
    这本来就是应用层的问题,你们非要往网络层扯?

    我家鸡蛋孵出来了一只鸡,但是这只鸡不会飞是什么原因?
    粘包警察:鸡蛋都没有翅膀,怎么可能会飞!
    ming159
        66
    ming159   101 天前
    “TCP 的粘包问题” 确实不严谨.这点我也承认.

    "基于 TCP 传输数据,必然存在应用层数据的 粘包 /拆包问题".

    如果写过 TCP 通信(Socket 编程)的懂得自然懂,不懂得说多了也没用, 可以参考 Netty 中的
    LineBasedFrameDecoder : 基于回车换行符的解码器
    DelimiterBasedFrameDecoder: 分隔符解码器,可以指定消息结束的分隔符
    FixedLengthFrameDecoder: 固定长度解码器,它能够按照指定的长度对消息进行自动解码
    LengthFieldBasedFrameDecoder :一般协议头中带有长度字段,通过使用 LengthFieldBasedFrameDecoder 传入特定的参数,来解决拆包粘包
    ZHanYao
        67
    ZHanYao   101 天前   ❤️ 6
    @msaionyc #62 严格来说是这样的,但是人与人沟通没必要这么抠字眼,能理解就行,就像叫人吃饭,难道就真的只吃饭不吃菜?

    楼主只是想找个在应用层可以处理粘包问题的框架,并没有将“粘包问题”甩锅给 TCP 的意思,但是为什么要抓住这个点不放呢?
    paoqi2048
        68
    paoqi2048   101 天前
    自己包下 net 库吧
    ming159
        69
    ming159   101 天前
    @darknoll 不是说所有协议都是这种模式"magic number+数据长度". 自己研究去吧
    95276
        70
    95276   101 天前
    @ZHanYao 因为抓不到其他的点.
    tairan2006
        71
    tairan2006   101 天前
    不需要框架,直接用 net 包就行

    一般用 bufio.Scanner 的 Split 就可以拆分 token 了

    如果想简单点可以直接用 websocket
    deavorwei
        72
    deavorwei   101 天前
    @ming159 您好,请教下粘包的问题。TCP 有重传机制和 ACK 机制,经过 TCP 传输的数据包应该是可靠的。应用层拿到的数据包应该也是完整的、有序的,为何会出现应用层接收到数据包是不完整或者是乱序的情况。---来自没有开发经验的小学生
    nowgoo
        73
    nowgoo   101 天前   ❤️ 6
    是个程序员都明白,人家问的就是应用层有没有“从字节流中拆出消息”的轮子。粘包警察纠着“粘包”两个字不放有意思吗?难道楼主不知道 TCP 是流协议,要你教?

    楼主明明说了使用“粘包”和“拆包”是因为描述方便。粘包警察会因为老婆饼里没老婆跟老板打一架吗?
    darknoll
        74
    darknoll   101 天前
    @ming159 那你得把问题表达出来啊,什么情况下不能用这种模式,问题都不说来别人怎么 show code 啊。
    blessingsi
        75
    blessingsi   101 天前 via Android
    @deavorwei 理解一下[流]协议这个说法。TCP 协议的有序性和完整性保证是针对整个流来说的,并不是代表接受端的每次 read 拿到的恰好是发送端每次 write 的内容。比如,当 TCP 一个包过大的时候,会在实际传输的时候拆开
    Lemeng
        76
    Lemeng   101 天前
    学习学习来的,绑定一下
    mxT52CRuqR6o5
        77
    mxT52CRuqR6o5   101 天前 via Android
    我觉得你需要的并不是裸 TCP
    marceliu323
        78
    marceliu323   101 天前
    我前几天正好写了一个序列化,反序列化消息到 struct 的库 https://github.com/lai323/bytecodec
    zxCoder
        79
    zxCoder   101 天前
    @nowgoo 真的是笑死了,粘包警察和 c++的语言律师简直就是编程界两大 sb
    Frytea
        80
    Frytea   101 天前
    ZeroMQ? 之前做 C 开发经常用
    maplelin
        81
    maplelin   101 天前
    @deavorwei #72 很简单的举例,水管漏了,中间有一部分数据丢掉了。但是不代表后面的数据就不能正确到达目的地。有序只是接受端和发送端会按照顺序发送数据和接受数据,并不代表每次都会等到收到接受端前一个数据已收到的状态码才发送下一段数据,这样效率是很低下的。
    Michaelssss
        82
    Michaelssss   101 天前
    你要写裸 TCP ?首先就是先定义 Frame 或者 Protocol,然后基于上述将 Payload 用于业务=。=详情见 HTTP 是怎么做的。。。一个意思
    ming159
        83
    ming159   101 天前
    @darknoll 54 楼 并不是虚构的协议. 可以参考
    1. Modbus ASCII 在 ASCII 传输模式下,消息帧以英文冒号”:”( 3A )开始,以回车( 0D )和换行( 0A )结束.
    2. 基恩士 PLC 中的 上位链路协议: [功能码] 开始,回车( 0D )结束.
    dbpe
        84
    dbpe   101 天前
    哈哈哈....笑死

    谁知道 http1.1 的长链接是怎么做的呢...


    斜眼笑
    ming159
        85
    ming159   101 天前
    @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$
    顺序没乱,且数据没丢.
    jsq2627
        86
    jsq2627   101 天前
    23333 当看到 LZ 写了“粘包”两字就猜到帖子的走向了。
    wengang285
        87
    wengang285   101 天前   ❤️ 1
    @ming159 长度( 4 字节)+buffer,缓冲区可读,那么查看先读长度,然后根据长度往后取 buffer,长度不够这次就不取,等待底层( epoll )的再次通知
    ace12
        88
    ace12   101 天前 via Android
    看到粘包,我就兴奋了哈哈哈
    SillyChenBrother
        89
    SillyChenBrother   101 天前   ❤️ 3
    TCP 没有所谓的粘包说法

    网络层,IP 数据报帮你分报,在这里会切块
    传输层,TCP 帮你分块,这里也会分块,但 UDP 就不会分

    TCP 传过来,你通过程序收到的数据肯定是不会破损的,都三次握手四次放手,拥塞控制,失败重传,流水线运输,传过来就都是对的数据。

    数据是一个流,过来的一个个报文,也就是所谓的包,你要自己处理数据边界,也就是说你自己定义的应用层协议必须处理如何区分边界的问题,比如发现开头是 Xx 就是你的一个切确的文本的开始,或者叫结构体的开始,直到 yyy 就是文本的结束,以此反复,也就是解码和编码的问题,也就是说这已经不是传输层的问题了,这是应用层了,参考 http,ftp 等协议,gRPC/thrift 这种序列化解编码就是你文中描述所需要用到,所以粘包的描述是多年来的玄之又玄的说法,每次听起来一头雾水,然后面试官还喜欢装逼问这个。

    设计好解编码二进制的序列化应用层协议,就没有所谓的粘包,拆包,朦朦胧胧,龙龙萌萌
    ming159
        90
    ming159   101 天前
    @wengang285
    但也可以是 长度( 4 字节)+buffer,缓冲区可读,那么查看先读长度,然后根据长度往后取 buffer,有多少取多少,因为没有取够, 那么下一次再次通知的时候,与上一次的已经取出来的拼接,直到取够 "长度" 为一次完整帧.
    tonyan93
        91
    tonyan93   101 天前
    粘包并不是 TCP 协议造成的,它的出现是因为应用层协议设计者对 TCP 协议的错误理解,忽略了 TCP 协议的定义并且缺乏设计应用层协议的经验。
    JoeBreeze
        92
    JoeBreeze   101 天前
    TCP: 你们在说啥?
    lesismal
        93
    lesismal   101 天前
    足够满足楼主和各位各种业务场景:
    https://github.com/lesismal/arpc
    lesismal
        94
    lesismal   101 天前
    @abersheeran 没办法,"粘包" 虽然是错误的概念,但已约定俗成,懂的人只是用这个词沟通问题
    D3EP
        95
    D3EP   101 天前
    Golang 这种阻塞 IO 模型还要什么框架..
    wengang285
        96
    wengang285   101 天前
    @ming159 也可以,但是这样会导致解码的逻辑多处理一个分支,增加代码的复杂性,但是并没有带来性能的提升,实际工程中不会这么写
    ming159
        97
    ming159   101 天前
    @wengang285 根据实际场景选择吧,例如 数据量相对较大,且 buffer 小的时候,如果不尽快从 buffer 中取出数据, 引发 流量控制机制,反而导致整体传输变慢.
    LewisW
        98
    LewisW   101 天前
    @noe132 你也太神了 顶级预测
    xuanbg
        99
    xuanbg   101 天前
    老老实实用一个 http 之类的应用层协议,而不是把 TCP 协议当应用层协议用,哪来的粘包。
    lesismal
        100
    lesismal   101 天前
    介绍下自己俩库,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
    1  2  
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2190 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 15:32 · PVG 23:32 · LAX 07:32 · JFK 10:32
    ♥ Do have faith in what you're doing.