之前做过一个深交所股票数据的接存储软件,消息的协议是这样。

协议文档在这  https://wenku.baidu.com/view/d102cd0b4a73f242336c1eb91a37f111f1850df2.html

由于socket接受来的数据会出现粘包或者半包的情况。所以要进行拆包处理代码是这样的,但是无论网络状态是否稳定都会出现丢包的情况。

  private RecMessage TryReadAmessage(ref byte[] bytes)
{
if (bytes.Length < )
return null;
var msgType = NetworkBitConverter.ToInt32(bytes, );
if (messageTypes.Contains(msgType))
{ var msgLength = NetworkBitConverter.ToInt32(bytes, );
if (msgLength >= && msgLength < )
{
if (bytes.Length < (msgLength + ))
return null; var outputByte = new byte[ + msgLength];
Array.Copy(bytes, outputByte, msgLength + );
bytes = bytes.Removebytes(msgLength + );
var chkbyte = new byte[];
Array.Copy(outputByte, msgLength + , chkbyte, , );
if (!GetBytesFomObj.CheckSum(chkbyte, outputByte)) return null; return new RecMessage
{
MessageType = msgType,
MessageLenght = msgLength,
MessageContent = outputByte.Removebytes()
};
}
else
bytes = bytes.Removebytes();
}
else
bytes = bytes.Removebytes();
return null;
}

后来用了supersocket框架拆包,效果不错,基本没有发现错误包的情况。看代码

  public class ClientBinaryFilter : FixedHeaderReceiveFilter<RecMessage>
{
/// <summary>
/// 所有消息类型
/// </summary>
private readonly int[] _messageTypes = new int[]
{ ,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
, };
public ClientBinaryFilter() : base()
{ }
private int key;
private int datalength;
protected override int GetBodyLengthFromHeader(IBufferStream bufferStream, int length)
{
key = bufferStream.ReadInt32(false);
datalength = bufferStream.ReadInt32(false);
return datalength + ;
} public override RecMessage ResolvePackage(IBufferStream bufferStream)
{
var buffer = new byte[datalength + ];
bufferStream.Skip().Read(buffer, , datalength + );
return new RecMessage
{
MessageType = key,
MessageLenght = datalength,
MessageContent = buffer
};
}
}

后来学习了golang语言,感觉非常适合做这种实时性很高的软件。由于逻辑不是特别复杂,没有用到所有的golang的特性,知识点有:net(socket),goruntime,channel(缓冲),数组切片slice,互斥锁sync.Mutex,redigo(redis),ffjson(序列化与反序列化)

核心的代码在这里

 //socket接受函数
func handMsgChannel(con net.Conn) {
con.Write(SendLogOn())
go sendHeartBt(con)
var unCompleteBytes []byte
for {
//startTime := time.Now()
buffer := make([]byte, )
readLength, err := con.Read(buffer)
CheckError(err, con)
if readLength > {
var readBuf []byte = buffer[:readLength]
//获取上次为解析的半包并装载到此次循环中解析
if len(unCompleteBytes) != {
readBuf = lib.BytesCopy(unCompleteBytes, readBuf)
}
readMessageChannel(&readBuf) //拆包分解,并把半包数据留在下次循环处理
unCompleteBytes = readBuf
//endTime := time.Since(startTime)
//fmt.Println("读取并数据处理时间: ", endTime)
}
}
} //利用channel读取并传入channel
func readMessageChannel(input *[]byte) {
//var output []BaseMsgModel
for {
byteArray := *input
//头+长度+校验 最小12个字节,不足跳出
if len(byteArray) < {
break
}
mt := lib.BytesToInt32(byteArray[:])
//获取数据头
if lib.Contain(mt, MsgTypes) {
ml := lib.BytesToInt32(byteArray[:])
//数据长度
if ml >= && ml < {
if len(byteArray) < +int(ml) {
break
}
//获取报文content
mc := byteArray[ : +int(ml)]
sum := lib.BytesToInt32(mc[len(mc)- : len(mc)])
checksum := lib.CheckSum(byteArray[ : +int(ml)])
//检查校验
if checksum == sum {
model := &BaseMsgModel{
mt,
ml,
mc,
}
chmsg <- model
*input = byteArray[+int(ml):]
} else {
*input = byteArray[+int(ml):]
fmt.Println("错误数据")
}
} else {
//错误长度移除
*input = byteArray[:]
fmt.Println("错误长度")
}
} else {
//错误头部移除
*input = byteArray[:]
fmt.Println("错误头")
}
}
} //分发存储channel中数据
func translateMsgChannel() {
for {
item := <-chmsg
//fmt.Print("数据类型", msgs.MsgType, "数据长度", msgs.MsgLength, msgs.MsgContent, "\r\n")
switch item.MsgType {
case :
msg.Save300111(item.MsgContent)
systemParams.Params.Lock()
systemParams.msg300111Length++
systemParams.Params.Unlock()
break
case :
msg.Save309011(item.MsgContent)
systemParams.Params.Lock()
systemParams.msg309011Length++
systemParams.Params.Unlock()
break
default:
break
}
systemParams.Params.Lock()
systemParams.RecLength++
systemParams.Params.Unlock()
}
}

经测试后不禁感叹golang真是黑科技,.net的代码内存会达到50M以上,CPU10%左右(I5 4核4线程)

golang呢10M左右 CPU 0.5%~1%,golang。。。牛啊!

代码在这  https://gitee.com/siming.liu/golang_stock

记一次golang的实践的更多相关文章

  1. Golang Gin实践 番外 请入门 Makefile

    Golang Gin实践 番外 请入门 Makefile 原文地址:Golang Gin实践 番外 请入门 Makefile 前言 含一定复杂度的软件工程,基本上都是先编译 A,再依赖 B,再编译 C ...

  2. Golang 高效实践之并发实践

    前言 在我前面一篇文章Golang受欢迎的原因中已经提到,Golang是在语言层面(runtime)就支持了并发模型.那么作为编程人员,我们在实践Golang的并发编程时,又有什么需要注意的点呢?下面 ...

  3. Golang 高效实践之并发实践context篇

    前言 在上篇Golang高效实践之并发实践channel篇中我给大家介绍了Golang并发模型,详细的介绍了channel的用法,和用select管理channel.比如说我们可以用channel来控 ...

  4. Golang高效实践之泛谈篇

    前言 我博客之前的Golang高效实践系列博客中已经系统的介绍了Golang的一些高效实践建议,例如: <Golang高效实践之interface.reflection.json实践>&l ...

  5. 知乎社区核心业务 Golang 化实践 - 知乎 https://zhuanlan.zhihu.com/p/48039838

    知乎社区核心业务 Golang 化实践 - 知乎 https://zhuanlan.zhihu.com/p/48039838

  6. 记一次golang内存泄露

    记一次golang内存泄露 最近在QA环境上验证功能时,发现机器特别卡,查看系统内存,发现可用(available)内存仅剩200多M,通过对进程耗用内存进行排序,发现有一个名为application ...

  7. 【GoLang】golang 最佳实践汇总

    最佳实践 1 包管理 1.1 使用包管理对Golang项目进行管理,如:godep/vendor等工具 1.2 main/init函数使用,init函数参考python 1.2.1 main-> ...

  8. Golang 高效实践之defer、panic、recover实践

    前言 我们知道Golang处理异常是用error返回的方式,然后调用方根据error的值走不同的处理逻辑.但是,如果程序触发其他的严重异常,比如说数组越界,程序就要直接崩溃.Golang有没有一种异常 ...

  9. 记一次golang的内存泄露

    程序功能 此程序的主要功能是将文件中数据导入到clickhouse数据库中. [问题描述] 服务器内存每隔一段时间会耗尽 [问题分析] 由于使用的是go语言开发的,所以采用了业界流行的工具pprof. ...

随机推荐

  1. 使用Ansible部署etcd 3.2高可用集群

    之前写过一篇手动搭建etcd 3.1集群的文章<etcd 3.1 高可用集群搭建>,最近要初始化一套新的环境,考虑用ansible自动化部署整套环境, 先从部署etcd 3.2集群开始. ...

  2. nginx accept() failed (24: Too many open files)

    nginx服务器出现如下信息: [crit] 17221#0: accept4() failed (24: Too many open files) [crit] 17221#0: accept4() ...

  3. 关于前一篇innodb自增列自己的一点补充

    上篇文章是我转载的,忘记注明了出处,在这里深感歉意.但是上篇文章中关于自增列预留ID的计算我当时怎么弄明白,后来自己想了想终于想通了,在这里详细解释一下. 我们以一次性插入10行为例,表格如下:  插 ...

  4. geoserver 源码介绍

    上一章我们通过实现一个服务对如何扩展GeoServer有了一定的了解,但是,对于为何要这样做并没有说明,本章我们重点来说说GeoServer的结构,下图来自GeoServer官网(希望没有侵权),它很 ...

  5. 第三章 RNA测序

    第三章 RNA测序   RNA测序(RNA Sequencing,简称RNA-Seq,也被称为全转录物组鸟枪法测序Whole Transcriptome Shotgun Sequencing,简称WT ...

  6. Vue.js2 + Laravel5 采用 CORS 方式解决 AJAX 跨域的问题

    一.建立中间件 php artisan make:middleware CorsAjax 二.编写中间件 CorsAjax <?phpnamespace App\Http\Middleware; ...

  7. Fiddler的钩子hook导致电脑无法连上网络

    今天,电脑怎么都无法连上网络,重启了几次电脑也不行,网络环境是没有问题的,后来同事告诉我,Fiddler有一个BUG,就是Fiddler获取钩子之后没有释放掉,必须启动Fiddler,再关闭Fiddl ...

  8. org.apache.hadoop.ipc.RemoteException: java.io.IOException:XXXXXXXXXXX could only be replicated to 0 nodes, instead of 1

    原因:Configured Capacity也就是datanode 没用分配容量 [root@dev9106 bin]# ./hadoop dfsadmin -report Configured Ca ...

  9. 2018.09.22 牧场的安排(状压dp)

    描述 农民 John 购买了一处肥沃的矩形牧场,分成M*N(1 <= M <= 12; 1 <= N <= 12)个 格子.他想在那里的一些格子中种植美味的玉米.遗憾的是,有些 ...

  10. hdu-1129(模拟题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1129 注意:c_code[i]=(p_code[i*k%n]-i)%28; #include<i ...