go语言开发证券实时行情转码接口(多个坑)

wangyanlb · · 7341 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

朋友给了一个c++的实时行情接口,其中实时分笔成交的结构体如下:

 

 1 typedef struct tagStockReport
 2     {
 3         WORD    wDataSize;                    //数据长度
 4         WORD    wChecked;                    //数据校验
 5 
 6         char    szCode[STOCKCODESIZE];        //股票代码,以'\0'结尾
 7         char    szName[STOCKNAMESIZE];        //股票名称,以'\0'结尾
 8 
 9         int        nTradingUnit;                //交易单位(每手多少股)
10 
11         long    ltime;                        // UCT
12 
13         float    fLastClose;                    // 昨收
14         float    fOpen;                        // 今开
15         float    fHigh;                        // 最高
16         float    fLow;                            // 最低
17         float    fNewPrice;                    // 最新
18         float    fVolume;                        // 成交量
19         float    fAmount;                        // 成交额
20 
21         float    fBuyPrice[BUYSELLCOUNT];    // 申买价1,2,3
22         float    fBuyVolume[BUYSELLCOUNT];    // 申买量1,2,3,
23         float    fSellPrice[BUYSELLCOUNT];    // 申卖价1,2,3
24         float    fSellVolume[BUYSELLCOUNT];    // 申卖量1,2,3
25     }TStockReport, *PStockReport;

 

我把其转化为go对应的结构体后,通过socket 接收推送过来的行情。

 

几个问题:1、c语言结构体的字段对齐规则似乎和go语言不一样,某些时候要在go接受的时候,补充一个空的占位字段。 2、如果一个结构体,里面除了有整形、浮点外,还有一些字符类型。 就没有办法对结构体所有字段统一的进行一次映射赋值。所以我只好把socket接受的数据切片逐片拼装到结构体中,各位老大,对于这种混合型的结构体,有没有好的统一解析socket数据流,进行赋值的方法。

上代码:

 

package main

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "github.com/axgle/mahonia"
    //"gopkg.in/mgo.v2"
    //"gopkg.in/mgo.v2/bson"
    //"log"
    //"io"
    "net"
    "os"
    //"time"
)

const (
    BZ         = "PUTDATA"
    MongodbUrl = "localhost:27017"
)

type StockFile struct {
    wDataSize    uint16   //数据长度
    wChecked     uint16   //数据校验
    szCode       [12]byte //股票代码,以'\0'结尾
    szName       [16]int8 //股票名称,以'\0'结尾
    nTradingUnit int32    //交易单位(每手多少股)
    //_            int16    //补位字段

    ltime       int32      // UCT
    fLastClose  float32    // 昨收
    fOpen       float32    // 今开
    fHigh       float32    // 最高
    fLow        float32    // 最低
    fNewPrice   float32    // 最新
    fVolume     float32    // 成交量
    fAmount     float32    // 成交额
    fBuyPrice   [5]float32 // 申买价1,2,3,4,5
    fBuyVolume  [5]float32 // 申买量1,2,3,4,5
    fSellPrice  [5]float32 // 申卖价1,2,3,4,5
    fSellVolume [5]float32 // 申卖量1,2,3,4,5

}

type StockDay struct {
    wDataSize    uint16     //数据长度0-1
    wChecked     uint16     //数据校验2-3
    szCode       string     //股票代码,以'\0'结尾4-15
    szName       string    //股票名称,以'\0'结尾
    nTradingUnit int32      //交易单位(每手多少股)
    ltime        int32      // UCT
    fLastClose   float32    // 昨收
    fOpen        float32    // 今开
    fHigh        float32    // 最高
    fLow         float32    // 最低
    fNewPrice    float32    // 最新
    fVolume      float32    // 成交量
    fAmount      float32    // 成交额
    fBuyPrice    [5]float32 // 申买价1,2,3,4,5
    fBuyVolume   [5]float32 // 申买量1,2,3,4,5
    fSellPrice   [5]float32 // 申卖价1,2,3,4,5
    fSellVolume  [5]float32 // 申卖量1,2,3,4,5

}

func main() {
    //在7076端口监听
    tcpAddr, err := net.ResolveTCPAddr("tcp", ":7076")
    checkError(err)
    listener, err1 := net.ListenTCP("tcp", tcpAddr)
    checkError(err1)
    fmt.Println("服务器准备就绪")

    for {
        //等待客户端的连接
        conn, err2 := listener.Accept()
        if err != nil {
            /*通常服务端为一个服务,不会因为错误而退出。出错后,继续等待下一个连接请求*/
            fmt.Println(err2)
            continue
        }
        fmt.Println("收到客户端的请求")
        go ServeClient(conn)
    }

}

func ServeClient(conn net.Conn) {
    defer conn.Close()
    defer fmt.Println("接收数据完成")
    fmt.Println("开始接受数据...")
    ReadHq(conn)
    return
}

/*读取验证数据*/
func ReadData(conn net.Conn) string {
    var data bytes.Buffer
    var buf [512]byte
    for {
        n, err := conn.Read(buf[0:])
        if err != nil {
            fmt.Println(err)
            return ""
        }
        //我们的数据以0做为结束的标记
        if buf[n-1] == 0 {
            //n-1去掉结束标记0
            data.Write(buf[0 : n-1])
            break
        } else {
            data.Write(buf[0:n])
        }
    }
    return string(data.Bytes())
}

func ReadHq(conn net.Conn) {

    var x StockDay
    var buf [1480]byte    
    dec := mahonia.NewDecoder("gbk")


    for {
        _, err := conn.Read(buf[0:148])
        if err != nil {
            fmt.Println(err)
            return
        }
        //b_buf := bytes.NewBuffer(buf[0:148])




        //分拆网络传过来的数据包
        binary.Read(bytes.NewBuffer(buf[0:2]), binary.LittleEndian, &x.wDataSize)
        binary.Read(bytes.NewBuffer(buf[2:4]), binary.LittleEndian, &x.wChecked)
        x.szCode = string(buf[4:16])
        x.szName = dec.ConvertString(string(buf[16:32]))        \\GBK 转  UTF8 
        binary.Read(bytes.NewBuffer(buf[32:36]), binary.LittleEndian, &x.nTradingUnit)
        binary.Read(bytes.NewBuffer(buf[36:40]), binary.LittleEndian, &x.ltime)
        binary.Read(bytes.NewBuffer(buf[40:44]), binary.LittleEndian, &x.fLastClose)
        binary.Read(bytes.NewBuffer(buf[44:48]), binary.LittleEndian, &x.fOpen)
        binary.Read(bytes.NewBuffer(buf[48:52]), binary.LittleEndian, &x.fHigh)
        binary.Read(bytes.NewBuffer(buf[52:56]), binary.LittleEndian, &x.fLow)
        binary.Read(bytes.NewBuffer(buf[56:60]), binary.LittleEndian, &x.fNewPrice)
        binary.Read(bytes.NewBuffer(buf[60:64]), binary.LittleEndian, &x.fVolume)
        binary.Read(bytes.NewBuffer(buf[64:68]), binary.LittleEndian, &x.fAmount)
        binary.Read(bytes.NewBuffer(buf[68:88]), binary.LittleEndian, &x.fBuyPrice)
        binary.Read(bytes.NewBuffer(buf[88:108]), binary.LittleEndian, &x.fBuyVolume)
        binary.Read(bytes.NewBuffer(buf[108:128]), binary.LittleEndian, &x.fSellPrice)
        binary.Read(bytes.NewBuffer(buf[128:148]), binary.LittleEndian, &x.fSellVolume)



        //binary.Read(b_buf, binary.LittleEndian, &x) //binary.LittleEndian  是内存中的字节序的概念,就是把低字节的放到了后面。网络传输一般用BigEndian,内存字节序和cpu有关,编程时要转化。
        fmt.Println(x)
        //fmt.Println(b_buf)

    }
    return
}

func SendData(conn net.Conn, data string) {
    buf := []byte(data)
    /*向 byte 字节里添加结束标记*/
    buf = append(buf, 0)
    _, err := conn.Write(buf)
    if err != nil {
        fmt.Println(err)
    }
}

func checkError(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(0)
    }
}

 


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:wangyanlb

查看原文:go语言开发证券实时行情转码接口(多个坑)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

7341 次点击  ∙  1 赞  
加入收藏 微博
1 回复  |  直到 2000-01-01 00:00:00
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传