jybateman jybateman -4 years ago 252
C Question

Go TCP read is non blocking

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"))
}

Answer Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download