golang网络socket粘包问题的解决方法_Golang

本文实例讲述了golang网络socket粘包问题的解决方法。分享给大家供大家参考,具体如下:

看到很多人问这个问题, 今天就写了个例子, 希望能帮助大家

首先说一下什么是粘包:百度上比较通俗的说法是指TCP协议中,发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

解决方案如下:

服务端:

复制代码 代码如下:

package main
import (
    "bytes"
    "encoding/binary"
    "fmt"
    "io"
    "net"
)
func main() {
    // 监听端口
    ln, err := net.Listen("tcp", ":6000")
    if err != nil {
        fmt.Printf("Listen Error: %s\n", err)
        return
    }
    // 监听循环
    for {
        // 接受客户端链接
        conn, err := ln.Accept()
        if err != nil {
            fmt.Printf("Accept Error: %s\n", err)
            continue
        }
        // 处理客户端链接
        go handleConnection(conn)
    }
}
func handleConnection(conn net.Conn) {
    // 关闭链接
    defer conn.Close()
    // 客户端
    fmt.Printf("Client: %s\n", conn.RemoteAddr())
    // 消息缓冲
    msgbuf := bytes.NewBuffer(make([]byte, 0, 10240))
    // 数据缓冲
    databuf := make([]byte, 4096)
    // 消息长度
    length := 0
    // 消息长度uint32
    ulength := uint32(0)
    // 数据循环
    for {
        // 读取数据
        n, err := conn.Read(databuf)
        if err == io.EOF {
            fmt.Printf("Client exit: %s\n", conn.RemoteAddr())
        }
        if err != nil {
            fmt.Printf("Read error: %s\n", err)
            return
        }
        fmt.Println(databuf[:n])
        // 数据添加到消息缓冲
        n, err = msgbuf.Write(databuf[:n])
        if err != nil {
            fmt.Printf("Buffer write error: %s\n", err)
            return
        }
        // 消息分割循环
        for {
            // 消息头
            if length == 0 && msgbuf.Len() >= 4 {
                binary.Read(msgbuf, binary.LittleEndian, &ulength)
                length = int(ulength)
                // 检查超长消息
                if length > 10240 {
                    fmt.Printf("Message too length: %d\n", length)
                    return
                }
            }
            // 消息体
            if length > 0 && msgbuf.Len() >= length {
                fmt.Printf("Client messge: %s\n", string(msgbuf.Next(length)))
                length = 0
            } else {
                break
            }
        }
    }
}

客户端:

复制代码 代码如下:

package main
import (
    "bytes"
    "encoding/binary"
    "fmt"
    "net"
    "time"
)
func main() {
    // 链接服务器
    conn, err := net.Dial("tcp", "127.0.0.1:6000")
    if err != nil {
        fmt.Printf("Dial error: %s\n", err)
        return
    }
    // 客户端信息
    fmt.Printf("Client: %s\n", conn.LocalAddr())
    // 消息缓冲
    msgbuf := bytes.NewBuffer(make([]byte, 0, 1024))
    // 消息内容
    message := []byte("我是utf-8的消息")
    // 消息长度
    messageLen := uint32(len(message))
    // 消息总长度
    mlen := 4 + len(message)
    // 写入5条消息
    for i := 0; i < 10; i++ {
        binary.Write(msgbuf, binary.LittleEndian, messageLen)
        msgbuf.Write(message)
    }
    // 单包发送一条消息
    conn.Write(msgbuf.Next(mlen))
    time.Sleep(time.Second)
    // 单包发送三条消息
    conn.Write(msgbuf.Next(mlen * 3))
    time.Sleep(time.Second)
    // 发送不完整的消息头
    conn.Write(msgbuf.Next(2))
    time.Sleep(time.Second)
    // 发送消息剩下部分
    conn.Write(msgbuf.Next(mlen - 2))
    time.Sleep(time.Second)
    // 发送不完整的消息体
    conn.Write(msgbuf.Next(mlen - 6))
    time.Sleep(time.Second)
    // 发送消息剩下部分
    conn.Write(msgbuf.Next(6))
    time.Sleep(time.Second)
    // 多段发送
    conn.Write(msgbuf.Next(mlen + 2))
    time.Sleep(time.Second)
    conn.Write(msgbuf.Next(-2 + mlen - 8))
    time.Sleep(time.Second)
    conn.Write(msgbuf.Next(8 + 1))
    time.Sleep(time.Second)
    conn.Write(msgbuf.Next(-1 + mlen + mlen))
    time.Sleep(time.Second)
    // 关闭链接
    conn.Close()
}

希望本文所述对大家Go语言程序设计有所帮助。

时间: 2024-10-31 17:50:32

golang网络socket粘包问题的解决方法_Golang的相关文章

socket-C# Socket 粘包 半包 问题请教

问题描述 C# Socket 粘包 半包 问题请教 初学C#的Socket,求各位大侠指教个解决Socket粘包半包的方法. 我查阅了一些资料知道处理逻辑. 1,发送的消息都由包头+包体组成,包头解释包体长度 2,接收方定义个缓存区 3,判断接收的信息长度 4,先接收个包头 5,按照包头取包体 但是感觉好多逻辑不知道具体用代码怎么实现,请大侠指教. 伪代码也行,最最反应不过来的就是这个缓冲区怎么构建?? 它肯定得各种操作索引吧? 解决方案 http://www.cnblogs.com/solq/

数据丢失-TCP socket粘包的处理问题

问题描述 TCP socket粘包的处理问题 我在处理从接收缓存区取出来的字符串时会发现有包处于残缺状态.我把完整的包都处理出来了,只是那些不完整包头和包尾.我该怎么去处理呢,是丢掉还是保存下来等下个缓存区中的数据过来再重新贴好呢?

win8系统网络总是受限的三种解决方法

win8系统网络总是受限的三种解决方法   方法一: 1.在电脑右下角右键点击无线网图标,在弹出菜单中选择打开网络和共享中心 2.进入网络共享中心,点击打开"连接"右侧的WLAN 3.进入WLAN状态页面,显示无Internet访问权限,点击打开页面下方的属性按钮 4.进入WLAN属性页面,点击打开配置按钮

解决TCP网络传输“粘包”问题

当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API).TCP/IP传输层有两个并列的协议:TCP和UDP.其中TCP(transport control protocol,传输控制协议)是面向连接的,提供高可靠性服务.UDP(user datagram protocol,用户数据报协议)是无连接的,提供高效率服务.在实际工程应用中,对可靠性和效率的选择取决于应用的环境和需求.一般情况下,普通数据的网络传输采用高效率的udp,重要数据的网络传输采用

解决TCP网络传输“粘包”问题,互联网营销

当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API).TCP/IP传输层有两个并列的协议:TCP和UDP.其中TCP(transport control protocol,传输控制协议)是面向连接的,提供高可靠性服务.UDP(user datagram protocol,用户数据报协议)是无连接的,提供高效率服务.在实际工程应用中,对可靠性和效率的选择取决于应用的环境和需求.一般情况下,普通数据的网络传输采用高效率的udp,重要数据的网络传输采用

处理TCP网络传输“粘包”疑难

在应用开发过程中,笔者发现基于TCP网络传输的应用程序有时会出现粘包现象(即发送方发送的若干包数据到接收方接收时粘成一包).针对这种情况,我们进行了专题研究与实验.本文重点分析了TCP网络粘包问题,并结合实验结果提出了解决该问题的对策和方法,供有关工程技术人员参考. 一.TCP协议简介 TCP是一个面向连接的传输层协议,虽然TCP不属于iso制定的协议集,但由于其在商业界和工业界的成功应用,它已成为事实上的网络标准,广泛应用于各种网络主机间的通信. 作为一个面向连接的传输层协议,TCP的目标是为

网络速度变慢的常见解决方法

   以下是导致网络缓慢的常见问题,以及一些常见网络问题的解决方法,在此整理给各位网友.(互联网搜集)   一.网络自身问题         您想要连接的目标网站所在的服务器带宽不足或负载过大.处理办法很简单,请换个时间段再上或者换个目标网站.   二.网线问题导致网速变慢         我们知道,双绞线是由四对线按严格的规定紧密地绞和在一起的,用来减少串扰和背景噪音的影响.同时,在T568A标准和T568B标准中仅使用了双绞线的 1.2和3.6四条线,其中,1.2用于发送,3.6用于接收,而

开机提示网络上有重名的解决方法

笔者记得前段时间单位里新买了一批电脑,刚安装完,逐渐有同事来问各种问题,比方说今天这个:右下角弹出窗口,提示"网络上有重名",上网断断续续的,怎么办?这是大批量装机的后遗症,改一下计算机名字就好了. 网络上有重名 网络上有重名的解决办法: 解决网络上有重名提示的办法就是修改计算机名字,具体步骤是: 在桌面"我的电脑"上右键单击,选择"属性",在弹出窗口中寻找"计算机名"标签,点击后在计算机名页面下面点击"更改&quo

ANT连接linux缺少jsch.jar及添加jar包无效的解决方法

本地安装Ant1.8.3,MyEclipse8.6关联Ant, 运行build.xml出现如下异常: 解决方法: 将 jsch-x.x.x.jar 加入到 ${ANT_HOME}/lib下,此时一般就可以了: 但是本人测试,还是不行,后来发现,需要重新导入ant的jar包才可以,方法如下: 此时,就没有问题了. 查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/Java/