Conn (net.Conn) does not write always on socket

I have done an application with a server and client to send information with a socket TCP

The problem is, if the function zfs.ReceiveSnapshot (in server side) does not return an error (err == nil), conn.Write([]byte("0")) does not work and the client does not receive any byte to continue and it cannot close the connection… The client side waiting infinite.

I show you the code of server and client

[EDIT]

Server:

package main

import (
    "net"
    "github.com/mistifyio/go-zfs"
)

func main() {
    // Listen for incoming connections
    l, _ := net.Listen("tcp", ":7766")

    // Close the listener when the application closes
    defer l.Close()
    fmt.Println("Listening on port 7766...")
    for {
        // Listen for an incoming connection.
        conn, _ := l.Accept()
        // Handle connections in a new goroutine.
        go handleRequest(conn)
    }
}

// Handles incoming requests
func handleRequest(conn net.Conn) {
    // Receive snapshot
    _, err := zfs.ReceiveSnapshot(conn, "tank/replication")
    if err != nil {
        conn.Write([]byte("11"))
        zfs.ReceiveSnapshot(conn, "tank/replication")
        conn.Close()
    }
    conn.Write([]byte("1"))
    conn.Close()
}

Client:

package main

import (
    "net"
    "github.com/mistifyio/go-zfs"
)

func main() {
    conn, _ := net.Dial("tcp", "192.168.99.5:7766")

    for i := 0; i < 1; i++ {
        // Get all snapshots in tank/test
        take, _ := zfs.Snapshots("tank/test")

        // Select snapshots
        snap := take[0].Name
        ds1, _ := zfs.GetDataset(snap)

        // Send first snapshot
        ds1.SendSnapshot(conn)
        defer conn.Close()

        buff := make([]byte, 8)
        n, _ := conn.Read(buff)

        if n > 1 {
            snap = take[1].Name
            ds2, _ := zfs.GetDataset(snap)
            zfs.SendSnapshotIncremental(conn, ds1, ds2, zfs.IncrementalStream)
            conn.Close()
        }
    }
}

If ReceiveSnapshots returns an error, conn.Write([]byte ) writes “1”, the cliente receives it, execute SendSnapshotIncremental (it does if n > 0) and close the connection in client side… But, if ReceiveSnapshot does not return an error, conn.Write([]byte("")) does not work just only I close the connection in server side with ctrl+C, then the client receives n == 0 and close the connection.

I think the problem is, if ReceiveSnapshot does not return error, it waits to receive plus and plus…

Somebody can help me please?

This writes zero bytes to the connection, which is not detectable from the other side.

I have changed the values of:

buff := make ([]byte, 8)
and the two conn.Write([]byte(“11”)) and conn.Write([]byte(“1”))

does not work…

I absolutely sure that the problem is, if the first zfs.ReceiveSnapshot does not return error, it waits infinite and does not run the next code…

Check all errors, add some tracing to find out where you are blocking. Note that a Read() can return less data than you asked for, and that it can return both data and an error. Check your errors. See if you can reproduce it without the zfs functions.

1 Like

I checked all errors with fmt.Println and changing the size of buffer to 1 but the problem continues. Maybe the problem is the function ReceiveSnapshot:

func ReceiveSnapshot(input io.Reader, name string) (*Dataset, error) {
	c := command{Command: "zfs", Stdin: input}
	_, err := c.Run("receive", name)
	if err != nil {
		return nil, err
	}
	return GetDataset(name)
}

If I don’t write conn.Close() after ReceiveSnapshot, this function continues waiting for data

Does that function ever return? I would expect zfs receive to read as long as its standard in is not closed, or until an error occurs.

Yes, it works. I think I have found the problem. If ReceiveSnapshot does not return error, it waits and in the client side, conn.Read waits also, so they wait for infinite because anybody does nothing…

Maybe with a timeout before first ReceiceSnapshot function…

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