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

协议文档在这  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. ASP.NET使用ListView数据绑定控件和DataPager实现数据分页显示(一)

    为什么使用ListView+DataPager的方式实现分页显示? .net提供的诸多数据绑定控件,每一种都有它自己的优点和缺点.如果需要对数据进行操作,如果数据量不大的情况下,DataList和Gr ...

  2. python之socket运用之执行命令

    服务端的代码 import socket import subprocess HOST = "127.0.0.1" PORT = 5001 ip_bind = (HOST,PORT ...

  3. 零基础学习hadoop到上手工作线路指导(初级篇)

    零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.在刚接触云计算,曾经想过培训,但是培训机构的选择就让我很纠结.所以索性就自己学习了.整个过程整理一下,给大家参考,欢迎讨论,共同学习. ...

  4. Nmap参数说明

    Nmap(Network Mapper)是一款开放源代码的网络探测和安全审核工具.它的设计目标是快速地扫描大型网络,不适应于单一主机.Nmap使用检测IP数据包来确定访问的主机.提供的服务.数据包的类 ...

  5. Apache模块开发

    一.简介 Apache HTTP服务器是一个模块化的软件,使管理者可以选择核心中包含的模块以裁剪功能.可以在编译时选择被静态包含进httpd二进制映象的模块,也可以编译成独立于主httpd二进制映象的 ...

  6. DNA甲基化检测服务

    DNA甲基化检测服务 DNA甲基化是最早发现的基因表观修饰方式之一,真核生物中的甲基化仅发生于胞嘧啶,即在DNA甲基化转移酶(DNMTs)的作用下使CpG二核苷酸5'-端的胞嘧啶转变为5'-甲基胞嘧啶 ...

  7. TPM、read counts、RPKM/FPKM你选对了吗?

    TPM.read counts.RPKM/FPKM你选对了吗? 已有 3940 次阅读 2017-12-15 15:04 |个人分类:RNA-seq|系统分类:科普集锦|关键词:RNA-seq| RN ...

  8. Executor(二)ThreadPoolExecutor、ScheduledThreadPoolExecutor 及 Executors 工厂类

    Executor(二)ThreadPoolExecutor.ScheduledThreadPoolExecutor 及 Executors 工厂类 Java 中的线程池类有两个,分别是:ThreadP ...

  9. Android界面设计

    从继承关系来看,所有组件继承自View.容器也是继承自View,它能容纳别的View. 所有容器继承自ViewGroup.包括 FrameLayout, LinearLayout, RelativeL ...

  10. qrc转换成py