Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go TCP read is non blocking

Tags:

c

tcp

go

I am trying to make a server and client in Go, I have managed to communicate with the server and client. But the problem I have is that the TCP read in golang is non-blocking. What I would like to know if is it possible for the read in golang to be blocking like read in C. Thank You

EDIT:

Here is the source code of the server:

func Init_tcp() *net.TCPListener {
    laddr, err := net.ResolveTCPAddr("tcp", ":4243")
    if err != nil {
            log.Fatal(err)
    }
    tcp, err := net.ListenTCP("tcp", laddr)
    if err != nil {
            log.Fatal(err)
    }
    return tcp
}

func main() {
    tcp := Init_tcp()
    conn, _ := tcp.Accept()
    data := make([]byte, 512)
    conn.SetNoDelay(false)
    for {
            conn.Read(data)
            fmt.Println(data)
    }
}

and my client:

func Init_tcp() *net.TCPConn {
    laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:4243")
    if err != nil {
            log.Fatal(err)
    }
    tcp, err := net.DialTCP("tcp", nil, laddr)
    if err != nil {
            log.Fatal(err)
    }
    return tcp
}

func main() {
   tcp := Init_tcp()
   tcp.Write([]byte("hello world"))
}
like image 617
jybateman Avatar asked Nov 18 '14 16:11

jybateman


People also ask

Is TCP read blocking?

By default, TCP sockets are in "blocking" mode. For example, when you call recv() to read from a stream, control isn't returned to your program until at least one byte of data is read from the remote site. This process of waiting for data to appear is referred to as "blocking".

Is read () blocking?

By default, read() waits until at least one byte is available to return to the application; this default is called “blocking” mode. Alternatively, individual file descriptors can be switched to “non-blocking” mode, which means that a read() on a slow file will return immediately, even if no bytes are available.


1 Answers

Readers can return partial data. From the docs, "If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more."

This is an issue in any language, even if something like this happened to work for you in C: TCP just provides a stream of bytes that can be written to any time. Single writes might, by design, be broken up into multiple packets for transmission, and there's no built-in signal to the receiver saying where a single write/message/request ends. The application has to figure out its own way to signal boundaries. That can mean delimiters (\n) or implicit or explicit byte counts (HTTP's Content-Length is an explicit one).

To read a specific number of input bytes, you want io.ReadAtLeast or io.ReadFull. To read until some arbitrary condition is met you should just loop on the Read call as long as there is no error. (Then you may want to error out on on too-large inputs to prevent a bad client from eating server resources.) If you're implementing a text-based protocol you should consider net/textproto, which puts a bufio.Reader in front of the connection so you can read lines. To limit how long you'll wait to finish reading (so that a misbehaving client can't leave a goroutine hanging and using memory, etc. forever), look at the net functions with Deadline in the name (which are related to the Timeout functions on the Error types). The context package helps manage timeouts, deadlines, and cancellation, and is especially useful if, for example, you're writing a complex server that's going to do many network operations every request.

The sample code has a possibly unrelated but important problem: it throws away errors from the Read and Write. That could mask simple problems and make them very hard to debug. If you have problems after accounting for partial reads, check all errors before asking for more help. Look at errcheck to make sure mistakes like this don't get into production.

like image 133
twotwotwo Avatar answered Sep 20 '22 15:09

twotwotwo