我的编程空间,编程开发者的网络收藏夹
学习永远不晚

go语言处理TCP拆包/粘包的具体实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

go语言处理TCP拆包/粘包的具体实现

目录

part 1

part 2

part 3

part 1

最近在学习go自带的rpc,看完了一遍想着自己实现一个codec,也就是自定义消息的序列化和反序列化。消息的序列化和反序列化涉及到两步:

1、从网络中读取数据和将数据写到网络中;

2、根据拿到的二进制数据反序列化以及把现有的对象序列化成二进制数据。而这个过程中就需要处理TCP的拆包粘包了。

TCP的拆包/粘包也算是网络编程中一个比较基础的问题了,具体的问题含义和解决方式也不再详细描述了。虽然作为实现应用层逻辑的程序员可能根本不需要关心这个,作为中间件的开发,同时也出于学习go语言的目的,还是稍微进行一下练习。

part 2

TCP拆包粘包的解决思路:在读取数据时,将读取到的二进制数据在正确的位置进行分割即可。这里直接使用head+body的方式,也就是在发送数据时先将整个数据的大小附加在数据前,就像这样:

+++++++++++++++++++++++++++++++++++++
size (2 bytes)  | body (size bytes)
+++++++++++++++++++++++++++++++++++++

这里将数据包的size作为head
注:这里举的例子里,size占2个byte;size具体占用的byte数可以根据实际情况决定

part 3

server具体实现:


func doConn(conn net.Conn) {
    var (
        buffer = bytes.NewBuffer(make([]byte, 0, BUF_SIZE)) //buffer用来缓存读取到的数据
        readBytes = make([]byte, BUF_SIZE) //readBytes用来接收每次读取的数据,每次读取完成之后将readBytes添加到buffer中
        isHead = true //用来标识当前的状态:正在处理size部分还是body部分
        bodyLen = 0 //表示body的长度
    )
    for {
        //首先读取数据
        readByteNum, err := conn.Read(readBytes)
        if err != nil {
            log.Fatal(err)
            return
        }
        buffer.Write(readBytes[0:readByteNum])//将读取到的数据放到buffer中
        // 然后处理数据
        for {
            if isHead {
                if buffer.Len() >= HEAD_SIZE {
                    isHead = false
                    head := make([]byte, HEAD_SIZE)
                    _, err = buffer.Read(head)
                    if err != nil {
                        log.Fatal(err)
                        return
                    }
                    bodyLen = int(binary.BigEndian.Uint16(head))
                } else {
                    break;
                }
            }
            if !isHead {
                if buffer.Len() >= bodyLen {
                    body := make([]byte, bodyLen)
                    _, err = buffer.Read(body[:bodyLen])
                    if err != nil {
                        log.Fatal(err)
                        return
                    }
                    fmt.Println("received body: " + string(body[:bodyLen]))
                    isHead = true
                } else {
                    break;
                }
            }
        }
    }
    func HandleTcp() {
 listener, err := net.Listen("tcp", ":1234")
 if err != nil {
  log.Fatal(err)
  return
 }
 log.Println("start listening on 1234")
 for {
  conn, err := listener.Accept()
  if err != nil {
   log.Fatal(err)
   return
  }
  go doConn(conn)
 }
}

client具体实现:


func SendStringwithTcp(arg string) error {
 conn, err := net.Dial("tcp", ":1234")
 if err != nil {
  log.Fatal(err)
  return err
 }
 head := make([]byte, server.HEAD_SIZE)
 content := []byte(arg)
 headSize := len(content)
 binary.BigEndian.PutUint16(head, uint16(headSize))
    //先写入head部分,再写入body部分
 _, err = conn.Write(head)
 if err != nil {
  log.Fatal(err)
  return err
 }
 _, err = conn.Write(content)
 if err != nil {
  log.Fatal(err)
  return err
 }
 return nil
}

到此这篇关于go语言处理TCP拆包/粘包的文章就介绍到这了,更多相关go语言 TCP拆包/粘包内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

go语言处理TCP拆包/粘包的具体实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

go语言处理TCP拆包/粘包的具体实现

目录part 1part 2part 3part 1最近在学习go自带的rpc,看完了一遍想着自己实现一个codec,也就是自定义消息的序列化和反序列化。消息的序列化和反序列化涉及到两步: 1、从网络中读取数据和将数据写到网络中; 2、根据
2022-06-07

go语言如何处理TCP拆包/粘包

这篇文章主要讲解了“go语言如何处理TCP拆包/粘包”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“go语言如何处理TCP拆包/粘包”吧!part 1最近在学习go自带的rpc,看完了一遍想着
2023-06-22

go语言实现简易比特币系统钱包的原理解析

钱包基础概念广义上,钱包是一个应用程序,为用户提供交互界面。钱包控制用户访问权限、管理比特比地址及秘钥、跟踪余额、创建交易和签名交易狭义上,即从程序员角度来看,“钱包”是指用于存储和管理用户秘钥的数据结构钱包是私钥的容器,一般是通过结构化文
2022-06-07

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录