文档章节

Golang实现简单tcp服务器04 -- 服务器的粘包处理

victoriest
 victoriest
发布于 2015/06/02 22:37
字数 749
阅读 664
收藏 8

服务器的粘包处理

什么是粘包

一个完成的消息可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和封包问题

TCP粘包和拆包产生的原因

  1. 应用程序写入数据的字节大小大于套接字发送缓冲区的大小

  2. 进行MSS大小的TCP分段。MSS是最大报文段长度的缩写。MSS是TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个的TCP报文段。所以MSS并不是TCP报文段的最大长度,而是:MSS=TCP报文段长度-TCP首部长度

  3. 以太网的payload大于MTU进行IP分片。MTU指:一种通信协议的某一层上面所能通过的最大数据包大小。如果IP层有一个数据包要传,而且数据的长度比链路层的MTU大,那么IP层就会进行分片,把数据包分成托干片,让每一片都不超过MTU。注意,IP分片可以发生在原始发送端主机上,也可以发生在中间路由器上。

TCP粘包和拆包的解决策略

  1. 消息定长。例如100字节。
  2. 在包尾部增加回车或者空格符等特殊字符进行分割,典型的如FTP协议
  3. 将消息分为消息头和消息尾。
  4. 其它复杂的协议,如RTMP协议等。

参考(http://blog.csdn.net/initphp/article/details/41948919)

我们的处理方式

解决粘包问题有多种多样的方式, 我们这里的做法是:

  • 发送方在每次发送消息时将消息长度写入一个int32作为包头一并发送出去, 我们称之为Encode
  • 接受方则先读取一个int32的长度的消息长度信息, 再根据长度读取相应长的byte数据, 称之为Decode

在实验环境中的主文件夹内, 新建一个名为codec的文件夹在其之下新建一个文件codec.go, 将我们的Encode和Decode方法写入其中, 这里给出Encode与Decode相应的代码:

codec.go

package codec

import (
	"bufio"
	"bytes"
	"encoding/binary"
)

func Encode(message string) ([]byte, error) {
	// 读取消息的长度
	var length int32 = int32(len(message))
	var pkg *bytes.Buffer = new(bytes.Buffer)
	// 写入消息头
	err := binary.Write(pkg, binary.LittleEndian, length)
	if err != nil {
		return nil, err
	}
	// 写入消息实体
	err = binary.Write(pkg, binary.LittleEndian, []byte(message))
	if err != nil {
		return nil, err
	}

	return pkg.Bytes(), nil
}

func Decode(reader *bufio.Reader) (string, error) {
	// 读取消息的长度
	lengthByte, _ := reader.Peek(4)
	lengthBuff := bytes.NewBuffer(lengthByte)
	var length int32
	err := binary.Read(lengthBuff, binary.LittleEndian, &length)
	if err != nil {
		return "", err
	}
	if int32(reader.Buffered()) < length+4 {
		return "", err
	}
	
	// 读取消息真正的内容
	pack := make([]byte, int(4+length))
	_, err = reader.Read(pack)
	if err != nil {
		return "", err
	}
	return string(pack[4:]), nil
}

这里就不帖服务器与客户端的调用代码了, 同学们自己动手试试~

相关源码: https://git.oschina.net/victoriest/go-simple-tcp-server.git

© 著作权归作者所有

victoriest
粉丝 5
博文 4
码字总数 2673
作品 0
武汉
高级程序员
私信 提问
TCP 粘包问题浅析及其解决方案

最近一直在做中间件相关的东西,所以接触到的各种协议比较多,总的来说有TCP,UDP,HTTP等各种网络传输协议,因此楼主想先从协议最基本的TCP粘包问题搞起,把计算机网络这部分基础夯实一下。...

haifeiWu
2018/07/24
0
0
GO语言手动处理TCP粘包

应用场景 大部分TCP通讯场景下,使用自定义通讯协议 image.png 粘包处理原理:通过请求头中数据包大小,将客户端N次发送的数据缓冲到一个数据包中 例如: 请求头占3个字节(指令头1字节、数据...

怪咖_OOP
2017/12/10
0
0
Golang通过Thrift框架完美实现跨语言调用

  每种语言都有自己最擅长的领域,Golang 最适合的领域就是服务器端程序。   做为服务器端程序,需要考虑性能同时也要考虑与各种语言之间方便的通讯。采用http协议简单,但性能不高。采用...

qinerg
2013/09/29
27.7K
19
Netty精粹之TCP粘包拆包问题

粘包拆包问题是处于网络比较底层的问题,在数据链路层、网络层以及传输层都有可能发生。我们日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生这个问题,因此这篇文章只...

Float_Luuu
2016/02/27
17.6K
0
Netty5入门学习笔记002-TCP粘包/拆包问题的解决之道(上)

TCP网络通信时候会发生粘包/拆包的问题,接下来探讨其解决之道。 什么是粘包/拆包 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据。TCP通讯为何存在粘包呢?主要原因是...

山东-小木
2014/12/17
15.1K
11

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周四乱弹 —— 当你简历注水但还是找到了工作

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @花间小酌 :#今日歌曲推荐# 分享成龙的单曲《男儿当自强》。 《男儿当自强》- 成龙 手机党少年们想听歌,请使劲儿戳(这里) @hxg2016 :刚在...

小小编辑
今天
2.8K
22
靠写代码赚钱的一些门路

作者 @mezod 译者 @josephchang10 如今,通过自己的代码去赚钱变得越来越简单,不过对很多人来说依然还是很难,因为他们不知道有哪些门路。 今天给大家分享一个精彩的 GitHub 库,这个库整理...

高级农民工
昨天
4
0
用好项目管理工具,人人都可以成为项目经理

现在市面上的项目管理工具越来越多了,但是大多数都是一些协同工具或轻量项目管理工具。如果是多团队、跨部门使用或者企业级的项目管理,从管理思想到工具运用,需要适应企业的业务流程体系,...

cs平台
昨天
12
0
只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
69
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
32
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部