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. W
Reader
s 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.