Hi I was under this impression, too I think for my purposes is Better to use a TLV based stream, also because I am familiar with TLVs. Which means, a naturally delimited syntax, as you said.
Thanks for the clarification on tcp read behavior. Thank On 20 May 2017 17:39, "Jesper Louis Andersen" < jesper.louis.ander...@gmail.com> wrote: Hi, TCP is a stream-oriented protocol. When you send your 1516 bytes, the receiver may read anything from 0 to 1516 bytes when they execute the read. The reason is that the operating system kernels in both ends are free to "chop up" the stream at any point. Furthermore, transmission errors and retransmissions may also affect what bytes you receive. If you attempt to use TCP as a message-oriented protocol it will fail eventually. Note that it could work in a test setting on localhost (where the kernel skips a lot of stuff and has a large MTU set), while failing once you hit the real world. If you want the guarantee you received a full message, you will have to consume data and then check if you have enough data for completing the message. Otherwise you loop again and buffer up more data from the stream. Two usual solutions which are fairly common: 1. Use framing. Prefix your message with a size, for instance a 4 byte header, big endian 32 bit unsigned integer. Then read until you have that many bytes in your buffer before continuing processing. The 4 byte overhead is usually negligible, unless you are sending very short messages. In a 1516 byte message, the overhead is close to 0.2%. 2. Use a format with a natural boundary. You read into a buffer and then attempt a decode. If the decode succeeds, you pass the message on and continue with the rest of the stream. If the decode fails, you request more bytes. Knowing how many more bytes you need allow for a nice optimization here. For instance, a JSON file is self-delimiting provided all your values are wrapped in either [] or {}. You simply scan for the end ] or } while keeping track of what you already parsed in a stack. A protobuf encoding is not. Personal subjective advice: Use method 1 above and introduce framing. Don't try to pack the integer in a variable-width encoding, just make it easy for the system to handle the integer. More bandwidth is far cheaper than more CPU or lower energy usage. Read 4 bytes, and determine how many bytes you need to read. Keep asking the kernel for streamed bytes until you have this amount. Then decode the message and start processing the next one. If you try to avoid the framing, it becomes far harder to implement correctly for a client since the framing decoder can't be kept separate from a syntactical/semantic encoder. In my experience, here be dragons and krakens. Sinister advice: if you need a byte which encodes the type of a message so it can be discriminated from others, encode the data in the order Length/Payload/Type rather than Length/Type/Payload. If the Type is in the suffix it forces programmers to decode everything into a buffer properly first which tend to remove some errors common to framing decoders. On Sat, May 20, 2017 at 5:01 PM <fusi.enrico.ma...@gmail.com> wrote: > Hello All > > first I apologize for my English, I'm not a native speaker. > I have a question about how golang reads the sockets in tcp. > > Imagine I send , using a conn.Write(buffer), a buffer which has the > (unpredictable) size from 80 Bytes to 1516. > > Now, if I do something like this (after creating "ln"): > > for { >> message := make([]byte, 1516) >> var err error >> // accept connection on port >> conn, _ := ln.Accept() >> mytimeout := 1000 >> mytimeout, _ = strconv.Atoi(cf.GConfig["TimeOut"]) >> Gtimeout := time.Duration(mytimeout) * time.Millisecond >> conn.SetReadDeadline(time.Now().Add(Gtimeout)) >> >> _, err = conn.Read(message) >> if err != nil { >> conn.Close() >> continue >> } > > *messageinterpreter(message) // just do something with message* > > } > > > what I am afraid is that , when the client is sending i.e 100 chars using > conn.Write(100chars) , the conn.Read will not understand the size, and not > stop until it has read 1516 bytes > > What is the expected behavior in such a case? I cannot serialize this > content (which is binary) because I fear the impact of overhead. > > > thanks in advance for any comment. > > EFM > > > > > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.