Sending binary packet via socket

Hi,

I started to learn Go recently and as part of my learning want to implement small network server which will talk with GPS device.

Protocol is very simple: first device sends its identifier, and if server wants to accept data from this device it should reply with 01 otherwise with 00. Responce should be send as binary packet. Previously, in Python this was done with sending bytes value b'\x01' or b'\x00'.

And here I’m stuck. Using following code I can succesfully receive initial packet with device ID, but I can’t find a way to send responce correctly. As result, second packet is always empty, device does not send any data.

func handleConnection(conn net.Conn) {
	remoteAddr := conn.RemoteAddr().String()
	fmt.Println("Client connected:", remoteAddr)

    buf := make([]byte, 1024)

    n, err := conn.Read(buf)
    if err != nil {
        fmt.Println("Read error", err.Error())
        conn.Close()
    }

    fmt.Println("Received bytes:", n)
    fmt.Println("ID", string(buf[2:17]))

    err = binary.Write(conn, binary.BigEndian, a)
    if err != nil {
        fmt.Println("Write error", err.Error())
        conn.Close()
    }

    n, err = conn.Read(buf)
    if err != nil {
        fmt.Println("Read error", err.Error())
        conn.Close()
    }

    fmt.Println("Received bytes:", n)
    fmt.Println("Data", string(buf[:n]))

I also tried to send data as

_, err = conn.Write([]byte{0x01})

and

var a byte = 1
t := new(bytes.Buffer)
err = binary.Write(t, binary.BigEndian, a)
if err != nil {
    fmt.Println("binary.Write failed:", err)
}
_, err = conn.Write(t.Bytes())

Am I doing something wrong?

Thanks and sorry for my English.

Your write is not wrong. (The binary.BigEndian and buffer things are needlessly convoluted compared to the simple conn.Write([]byte{1}) but also don’t look obviously broken to me.)

Thanks! I spend more time with debugging code and checking communication between server and client and seems first part works fine: server accepts data from the client and sends correct responce. But can not receive second packet with actual data.

Second call to n, err = conn.Read(buf) (after sending confirmation to the client) tells that zero bytes were received and data packet is empty. Is this expected? Probably I need to “reset” socket somehow to be able to read second packet from the client?

Read() does not necessary return all the data you expect in one go. Take a look at io.ReadFull.

Probably I was unclear. The problem is that after I write single byte with conn.Write([]byte{1}) I next call to conn.Read() returns zero bytes. I have an impression that it does not wait for data to arrive and connection closed immediately after last Read() was called and no data were received.

Am I right that to wait for data I need to use another approach, something like:

  1. start goroutine which will accept connections in a endless loop and store them into channel
  2. in connection handler start goroutine with endless loop which will wait for data from the socket and send them into another channel
  3. if data received — process them, send responce if necessary and again wait for data or close connection

No, you don’t need to do that. What does the error return say?

There is no error, I get following debug messages

Starting server...
Listening at 127.0.0.1:9999
Client connected: 127.0.0.1:40014
Receiving device ID...
Error <nil>
Received bytes 18
Packet content [49 49 51 53 49 53 49 51 48 53 50 49 56 54 52 49 53 10]
Sending responce...
Error <nil>
Sent bytes 1
Receiving data...
Error <nil>
Received bytes 0
Packet content []

Since you’re saying "packet’, is this UDP? In that case I guess you got an empty packet from the other side. Read again.

If not, might be they have closed the write side of the connection. Read again and you might see an EOF.

No, this is TCP. By packet I mean data, send by device.

I also tested with netcat, and it gets disconnected after receiving responce from the server. Adding another Read() does not help, it also reads zero bytes and don’t waits for any data to arrive.

That’s odd. Read of a TCP net.Conn in Go doesn’t return zero bytes and no error, repeatedly. (Unless the buffer is zero sized, which it isn’t in your code above.)

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.