朋友给了一个c++的实时行情接口,其中实时分笔成交的结构体如下
```go
typedef struct tagStockReport
{
WORD wDataSize; //数据长度
WORD wChecked; //数据校验
char szCode[STOCKCODESIZE]; //股票代码,以'\0'结尾
char szName[STOCKNAMESIZE]; //股票名称,以'\0'结尾
int nTradingUnit; //交易单位(每手多少股)
long ltime; // UCT
float fLastClose; // 昨收
float fOpen; // 今开
float fHigh; // 最高
float fLow; // 最低
float fNewPrice; // 最新
float fVolume; // 成交量
float fAmount; // 成交额
float fBuyPrice[BUYSELLCOUNT]; // 申买价1,2,3
float fBuyVolume[BUYSELLCOUNT]; // 申买量1,2,3,
float fSellPrice[BUYSELLCOUNT]; // 申卖价1,2,3
float fSellVolume[BUYSELLCOUNT]; // 申卖量1,2,3
}TStockReport, *PStockReport;
```
我把其转化为go对应的结构体后,通过socket 接收推送过来的行情。
上代码:
几个问题:1、c语言结构体的字段对齐规则似乎和go语言不一样,某些时候要在go接受的时候,补充一个空的占位字段。 2、如果一个结构体,里面除了有整形、浮点外,还有一些字符类型。 就没有办法对结构体所有字段统一的进行一次映射赋值。所以我只好把socket接受的数据切片逐片拼装到结构体中,各位老大,对于这种混合型的结构体,有没有好的统一解析socket数据流,进行赋值的方法。
```go
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)
}
}
```