This commit is contained in:
injoy
2024-10-27 00:45:56 +08:00
parent 05e0bcd693
commit ec6e93d845
8 changed files with 98 additions and 41 deletions

View File

@@ -1,7 +1,6 @@
package tdx
import (
"encoding/hex"
"github.com/injoyai/base/maps/wait/v2"
"github.com/injoyai/conv"
"github.com/injoyai/ios"
@@ -22,13 +21,18 @@ func Dial(addr string, op ...client.Option) (cli *Client, err error) {
cli.c, err = dial.TCP(addr, func(c *client.Client) {
c.Logger.WithHEX() //以HEX显示
c.SetOption(op...) //自定义选项
//c.Event.OnReadFrom = protocol.ReadFrom //分包
//c.AllReader = ios.NewAllReader(c.Reader.(io.Reader), protocol.ReadFrom) //分包
c.Event.OnReadFrom = protocol.ReadFrom //分包
c.Event.OnDealMessage = cli.handlerDealMessage //处理分包数据
logs.Debug("option")
})
if err != nil {
return nil, err
}
logs.Debug("run")
logs.Debugf("%#v\n", cli.c.Event.OnReadFrom)
go cli.c.Run()
err = cli.connect()
@@ -55,16 +59,23 @@ func (this *Client) handlerDealMessage(c *client.Client, msg ios.Acker) {
return
}
var resp any
switch f.Type {
case protocol.TypeSecurityQuote:
resp := protocol.MSecurityQuote.Decode(f.Data)
logs.Debug(resp)
this.w.Done(conv.String(f.MsgID), resp)
return
resp = protocol.MSecurityQuote.Decode(f.Data)
case protocol.TypeSecurityList:
resp, err = protocol.MSecurityList.Decode(f.Data)
}
_ = f
if err != nil {
logs.Err(err)
return
}
logs.Debug(resp)
this.w.Done(conv.String(f.MsgID), resp)
}
@@ -77,6 +88,7 @@ func (this *Client) SendFrame(f *protocol.Frame) (any, error) {
return this.w.Wait(conv.String(this.msgID))
}
// Send 向服务发送数据,并等待响应数据
func (this *Client) Send(bs []byte) (any, error) {
if _, err := this.c.Write(bs); err != nil {
return nil, err
@@ -84,6 +96,7 @@ func (this *Client) Send(bs []byte) (any, error) {
return this.w.Wait(conv.String(this.msgID))
}
// Write 实现io.Writer,向服务器写入数据
func (this *Client) Write(bs []byte) (int, error) {
return this.c.Write(bs)
}
@@ -99,23 +112,13 @@ func (this *Client) connect() error {
}
// GetSecurityList 获取市场内指定范围内的所有证券代码
// 0c02000000011a001a003e05050000000000000002000030303030303101363030303038
func (this *Client) GetSecurityList() (*protocol.SecurityListResp, error) {
f := protocol.Frame{
Control: 0x01,
Type: protocol.TypeConnect,
Data: nil,
}
_ = f
bs, err := hex.DecodeString("0c02000000011a001a003e05050000000000000002000030303030303101363030303038")
func (this *Client) GetSecurityList(exchange protocol.Exchange, starts ...uint16) (*protocol.SecurityListResp, error) {
f := protocol.MSecurityList.Frame(exchange, starts...)
result, err := this.SendFrame(f)
if err != nil {
return nil, err
}
_, err = this.Write(bs)
return nil, err
return result.(*protocol.SecurityListResp), nil
}

21
example/testlist/main.go Normal file
View File

@@ -0,0 +1,21 @@
package main
import (
"github.com/injoyai/logs"
"github.com/injoyai/tdx"
"github.com/injoyai/tdx/protocol"
)
func main() {
c, err := tdx.Dial("124.71.187.122:7709")
logs.PanicErr(err)
resp, err := c.GetSecurityList(protocol.ExchangeSH)
logs.PrintErr(err)
for _, v := range resp.List {
logs.Debugf("%#v\n", v)
}
select {}
}

2
go.mod
View File

@@ -8,6 +8,7 @@ require (
github.com/injoyai/goutil v0.0.0-20241009040015-3d20afe3efe6
github.com/injoyai/ios v0.0.3
github.com/injoyai/logs v1.0.9
golang.org/x/text v0.16.0
)
require (
@@ -59,7 +60,6 @@ require (
golang.org/x/net v0.27.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3 // indirect
google.golang.org/grpc v1.50.1 // indirect
google.golang.org/protobuf v1.31.0 // indirect

View File

@@ -1,12 +1,9 @@
package protocol
const (
Control = 0x01
)
const (
TypeConnect = 0x000d //建立连接
TypeHandshake = 0xdb0f //握手
TypeSecurityList = 0x0450 //获取股票代码
TypeSecurityQuote = 0x053e // 行情信息
)

View File

@@ -7,6 +7,7 @@ import (
"github.com/injoyai/base/bytes"
"github.com/injoyai/base/g"
"github.com/injoyai/conv"
"github.com/injoyai/logs"
"io"
)
@@ -34,7 +35,7 @@ Frame 数据帧
*/
type Frame struct {
MsgID uint32 //消息ID
Control uint8 //控制码,这个还不知道怎么定义
Control Control //控制码,这个还不知道怎么定义
Type uint16 //请求类型,如建立连接,请求分时数据等
Data []byte //数据
}
@@ -44,7 +45,7 @@ func (this *Frame) Bytes() g.Bytes {
data := make([]byte, 12+len(this.Data))
data[0] = Prefix
copy(data[1:], Bytes(this.MsgID))
data[5] = this.Control
data[5] = this.Control.Uint8()
copy(data[6:], Bytes(length))
copy(data[8:], Bytes(length))
copy(data[10:], Bytes(this.Type))
@@ -108,6 +109,7 @@ func Decode(bs []byte) (*Response, error) {
// ReadFrom 这里的r推荐传入*bufio.Reader
func ReadFrom(r io.Reader) (result []byte, err error) {
logs.Debug("ReadFrom")
prefix := make([]byte, 4)
for {
result = []byte(nil)
@@ -132,6 +134,7 @@ func ReadFrom(r io.Reader) (result []byte, err error) {
//获取后续字节长度
length := uint16(result[11])<<8 + uint16(result[10])
logs.Debug("长度:", length)
buf = make([]byte, length)
_, err = io.ReadFull(r, buf)
if err != nil {

View File

@@ -3,13 +3,14 @@ package protocol
import (
"errors"
"fmt"
"github.com/injoyai/conv"
"strings"
)
var (
MConnect = connect{}
MSecurityQuote = securityQuote{}
SecurityList = securityList{}
MSecurityList = securityList{}
)
type ConnectResp struct {
@@ -20,7 +21,7 @@ type connect struct{}
func (connect) Frame() *Frame {
return &Frame{
Control: Control,
Control: Control01,
Type: TypeConnect,
Data: []byte{0x01},
}
@@ -55,11 +56,12 @@ type Security struct {
type securityList struct{}
func (securityList) Frame() *Frame {
func (securityList) Frame(exchange Exchange, starts ...uint16) *Frame {
start := conv.DefaultUint16(0, starts...)
return &Frame{
Control: 0x01,
Type: TypeConnect,
Data: nil,
Control: Control01,
Type: TypeSecurityList,
Data: []byte{exchange.Uint8(), 0x0, uint8(start), uint8(start >> 8)},
}
}
@@ -69,11 +71,23 @@ func (securityList) Decode(bs []byte) (*SecurityListResp, error) {
return nil, errors.New("数据长度不足")
}
count := Uint16(bs[:2])
resp := &SecurityListResp{
Count: Uint16(bs[:2]),
}
bs = bs[2:]
_ = count
for i := uint16(0); i < resp.Count; i++ {
sec := &Security{
Code: String(bs[:6]),
VolUnit: Uint16(bs[6:8]),
Name: string(UTF8ToGBK(bs[8:16])),
PreClose: getVolume(Uint32(bs[16:20])),
}
bs = bs[20:]
resp.List = append(resp.List, sec)
}
return nil, nil
return resp, nil
}
@@ -139,7 +153,7 @@ type securityQuote struct{}
func (this securityQuote) Frame(m map[Exchange]string) (*Frame, error) {
f := &Frame{
Control: Control,
Control: Control01,
Type: TypeSecurityQuote,
Data: []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}

View File

@@ -42,3 +42,12 @@ func Test_getPrice(t *testing.T) {
t.Log(getPrice([]byte{0x7f, 0x3f, 0x40, 0x3f, 0x01})) //预期-63
t.Log(getPrice([]byte{0x2f, 0x3f, 0x40, 0x3f, 0x01})) //预期47
}
/*
0c000000000106000600500400000000
0c020000000106000600500400000000
*/
func Test_securityList_Frame(t *testing.T) {
f := MSecurityList.Frame(ExchangeSH, 0)
t.Log(f.Bytes().HEX())
}

View File

@@ -1,5 +1,15 @@
package protocol
type Control uint8
func (this Control) Uint8() uint8 {
return uint8(this)
}
const (
Control01 Control = 0x01 //好像都是01暂时不知道啥含义
)
type Exchange uint8
func (this Exchange) Uint8() uint8 { return uint8(this) }