Go writes a TCP server that sends four values of investment (start, high, low, closing, and time) to the client.
The first 8 bytes of data to send are the number of bytes in a four-valued structure represented by JSON followed by the actual JSON string.
I wrote a program like the one below to test this TCP server, but the client blocked Read for some reason (maybe there's something else on the server...) and it doesn't end well.
Why?
The following test program's Candle is a struct with 4 values.
The server side code is also listed below it.
The environment is x64 Linux, Go1.18
import(
"fmt"
"log"
"net"
"strconv"
"string"
"sync"
"time"
)
typeCandle structure {
Count int `json: "Count, omitempty"`
Open float64`json: "Open"`
Close float64`json: "Close"`
Low float64`json: "Low"`
High float64`json: "High"`
Datetime time.Time`json: "Datetime"`
}
funcmain(){
data_buf:=make([]byte, 1024*1024)
server_addr:="localhost"
port —=33333
port_str:="33333"
JST: = time.FixedZone ("JST", 9*60*60)
cs: = make ([]Candle, 0,200)
newline_sep: = strings.Split(data_csv, "\n") // data_csv is the csv string of the value of the Candle
for_,v:=range newline_sep{
varc Candle
comma_sep: = strings.Split(v, ", ")
date_str: =comma_sep[0]+"+comma_sep[1]
date,err: = time.ParseInLocation("January 2, 2006 15:04", date_str, JST)
if err!=nil{
log.Fatal(err)
}
c. Datetime=date
open,err: = strconv.ParseFloat(comma_sep[2],64)
if err!=nil{
log.Fatal(err)
}
high,err —= strconv.ParseFloat (comma_sep[3],64)
if err!=nil{
log.Fatal(err)
}
low,err —= strconv.ParseFloat (comma_sep[4],64)
if err!=nil{
log.Fatal(err)
}
clo,err —= strconv.ParseFloat (comma_sep[5],64)
if err!=nil{
log.Fatal(err)
}
c. Open=open
c. Close=clo
c. High = high
c. Low = low
cs = append(cs,c)
} // Create an array of Candles to be sent to the server so far
num_candle: =len(cs)
fmt.Println("num_candle", num_candle)
handle_chan:=make(chanCandle)
go func(server_chanCandle) {//Launching the server in a different routine, the server receives the Candle from server_chan and sends it to the client
s: = NewCandleServer(server_chan)
s.Run(server_addr, port)
}(candle_chan)
wg:=&sync.WaitGroup{}
wg.Add(1)
go func(){
time.Sleep (1500*time.Millisecond)
for_,v:=rangecs{
handle_chanlen(data_buf){
data_buf=make([]byte,size)
}
fmt.Println("read hang before")
_,err=conn.Read(data_buf)
fmt.Println("read hang")
if err!=nil{
log.Fatal("payload read error:", error)
}
i+=1
}
wg.Wait()
if i!=num_candle{
_= fmt.Errorf("something Error")
}
}
import(
"encoding/json"
"fmt"
"investment/calc"
"investment/kabucom3"
"log"
"net"
"strconv"
"sync"
)
typeServiceable interface {
kabucom3.PositionsSuccess | calc.Candle
}
funcByteLength(b[]byte)([]byte, int){
buff:=make([]byte,8)
b_len —=len(b)
b_len64 —=uint64(b_len)
for i —=0; i<8;i++{
buff[i]=byte((b_len64>>((7-i)*8))&byte(0xff)
}
buff=append(buff,b...)
return buff, b_len
}
typeCandleServer [T Serviceable] structure {
Conns* sync.Map
Cchan T
}
func(t*CandleServer[T])Run(addr string, port int){
prefer func(){
t.Conns.Range(func(k,vany)bool{
c: = k. (*net.Conn)
(*c).Close()
return true
})
}()
go func(){
variable = 0
for {
select{
casev:=<-t.C:
c+ = 1
fmt.Println("candle_server", "case", c)
b,err —=json.Marshal(v)
if err!=nil{
fmt.Println("hang",err)
}
result_buff,_ —=ByteLength(b)
t.Conns.Range(func(k,vany)bool{
c: = k. (*net.Conn)
_,err: =(*c).Write(result_buff)
if err!=nil{
(*c).Close()
t.Conns.Delete(k)
}
return true
})
fmt.Println("candle_server", "after range")
}
}
}()
ln,err: = net.Listen("tcp", addr+":"+strconv.Itoa(port))
if err!=nil{
log.Fatal("Listen Error", error)
}
for {
conn,err —=ln.Accept()
if err!=nil{
log.Fatal("Accept Error", error)
}
t.Conns.Store(&conn, structure{}{})
}
}
func NewCandleServer [T Serviceable] (cchan T)*CandleServer [T]{
return&CandleServer[T]{C:c,Conns:&sync.Map{}}
}
The io.Reader Read(buff) method is blocked until the buffer size has been received.
If the sender sends less than that, the Read will never complete.
A streaming decoder is standard for receiving JSON decode results.
var result map [string] interface {}
iferr:=json.NewDecorder(conn).Decode(&result);err!=nil{
error handling
}
Read the stream until it can be interpreted as JSON.
© 2024 OneMinuteCode. All rights reserved.