朋友给了一个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) } }