Getting EOF from server as client in Go -


i have go client custom protocol. protocol lz4-compressed json-rpc 4 byte header giving length of compressed json.

func receivemessage(conn net.conn) ([]byte, error) {     start := time.now()     bodylen := 0     body := make([]byte, 0, 4096)     buf := make([]byte, 0, 256)      bodylen == 0 || len(body) < bodylen {         if len(body) > 4 {             header := body[:4]             body = body[:4]             bodylen = int(unpack(header))         }          n, err := conn.read(buf[:])         if err != nil {             if err != io.eof {                 return body, err             }         }         body = append(body, buf[0:n]...)          := time.now()         if now.sub(start) > time.duration(readtimeout) * time.millisecond     {             return body, fmt.errorf("timed-out while reading socket.")         }         time.sleep(time.duration(1) * time.millisecond)     }      return lz4.decode(nil, body) } 

the client:

func main() {     address := os.args[1]     msg := []byte(os.args[2])      fmt.printf("sending %s %s\n", msg, address)      conn, err := net.dial(address)     if err != nil {         fmt.printf("%v\n", err)         return     }      // library call     _, err = sendmessage(conn, []byte(msg))     if err != nil {         fmt.printf("%v\n", err)         return     }      response, err := receivemessage(conn)     conn.close()      if err != nil {         fmt.printf("%v\n", err)         return     }      fmt.printf("response: %s\n", response) } 

when call it, no response , times out. (if not explicitly ignore eof, returns there io.eof error.) have library written in python works against same endpoint same payload. see immediately?

[jimb beat me answer here goes anyway.]

the root issue did body = body[:4] when wanted body = body[4:]. former keeps first 4 header bytes while latter tosses 4 header bytes decoded.

here self contained version debug logs works. has of other changes mentioned. (i guessed @ various things didn't include, lz4 package used, timeout, unpack, etc.)

package main  import (         "encoding/binary"         "errors"         "fmt"         "io"         "log"         "net"         "time"          "github.com/bkaradzic/go-lz4" )  const readtimeout = 30 * time.second // xxx guess  func receivemessage(conn net.conn) ([]byte, error) {         bodylen := 0         body := make([]byte, 0, 4096)         var buf [256]byte          conn.setdeadline(time.now().add(readtimeout))         defer conn.setdeadline(time.time{}) // disable deadline         bodylen == 0 || len(body) < bodylen {                 if bodylen == 0 && len(body) >= 4 {                         bodylen = int(unpack(body[:4]))                         body = body[4:]                         if bodylen <= 0 {                                 return nil, errors.new("invalid body length")                         }                         log.println("read bodylen:", bodylen)                         continue                 }                  n, err := conn.read(buf[:])                 body = append(body, buf[:n]...)                 log.printf("appended %d bytes, len(body) %d", n, len(body))                 // note, checked *after* handing n bytes.                 // io.reader allowed return data error.                 if err != nil {                         if err != io.eof {                                 return nil, err                         }                         break                 }         }         if len(body) != bodylen {                 return nil, fmt.errorf("got %d bytes, expected %d",                         len(body), bodylen)         }          return lz4.decode(nil, body) }  const address = ":5678"  var msg = []byte(`{"foo":"bar"}`)  func main() {         //address := os.args[1]         //msg := []byte(os.args[2])          fmt.printf("sending %s %s\n", msg, address)          conn, err := net.dial("tcp", address)         if err != nil {                 fmt.printf("%v\n", err)                 return         }          // library call         _, err = sendmessage(conn, msg)         if err != nil {                 fmt.printf("%v\n", err)                 return         }          response, err := receivemessage(conn)         conn.close()          if err != nil {                 fmt.printf("%v\n", err)                 return         }          fmt.printf("response: %s\n", response) }  // guess @ `unpack` func unpack(b []byte) uint32 {         return binary.littleendian.uint32(b) }  func sendmessage(net.conn, []byte) (int, error) {         // stub         return 0, nil }  func init() {         // start simple test server in same process go-routine.         ln, err := net.listen("tcp", address)         if err != nil {                 log.fatal(err)         }         go func() {                 defer ln.close()                 {                         conn, err := ln.accept()                         if err != nil {                                 log.fatalln("accept:", err)                         }                         go serve(conn)                 }         }() }  func serve(c net.conn) {         defer c.close()         // skip readding initial request/message , respond         const response = `{"somefield": "someval"}`         // (de)compression in go done streaming via         // io.reader or io.writer need final length.         data, err := lz4.encode(nil, []byte(response))         if err != nil {                 log.println("lz4 encode:", err)                 return         }         log.println("sending len:", len(data))         if err = binary.write(c, binary.littleendian, uint32(len(data))); err != nil {                 log.println("writing len:", err)                 return         }         log.println("sending data")         if _, err = c.write(data); err != nil {                 log.println("writing compressed response:", err)                 return         }         log.println("serve done, closing connection") } 

playground (but not runnable there).


Comments

Popular posts from this blog

java - Spring Data JPA: Why findOne(id) executing delete query internally? -

python - Mongodb How to add addtional information when aggregating? -

java - Incorrect order of records in M-M relationship in hibernate -