TCP is a stream oriented protocol, you need to add your own framing on
top of it. Think of a *net.TCPConn like a file. How would you separate
different entries while reading from that file.
There is also a trivial connection leak in your echoserver, you should
add a defer to close the conn in connhandler().
Cheers
Dave
On Wed, Sep 12, 2012 at 10:33 AM, Oliver Nispel <
oli...@nispel.org> wrote:
> I have two little go applications.
> echoclient.go sends textmessages to the server and echoserver.go receives
> these messages and returns them to the client.
>
> echoclient.go:
>
>
> package main
>
> import (
> "fmt"
> "log"
> "net"
> "time"
> )
>
> func connreader(c net.Conn) {
> for {
> readbuf := make([]byte, 1024)
> log.Println("reading from connection")
> _, err := c.Read(readbuf)
> if err != nil {
> log.Println("error while receiving from server")
> } else {
> log.Println("received from server: ", string(readbuf))
> }
> }
> }
>
> func main() {
> conn, err := net.Dial("tcp", "
127.0.0.1:8080")
> if err != nil {
> log.Fatal("cannot connect to server")
> }
> go connreader(conn)
> for l := 0; l < 10; l++ {
> sendstr := fmt.Sprintf("ping %02d", l)
> i, _ := conn.Write([]byte(sendstr))
> log.Printf("sent %d bytes\n", i)
> //time.Sleep(time.Millisecond * 500)
> }
> time.Sleep(time.Second * 10)
> }
>
>
> echoserver.go:
>
> package main
>
> import (
> "log"
> "net"
> )
>
> func connhandler(conn net.Conn) {
> log.Println("conn accepted from ", conn.RemoteAddr())
> for {
> buffer := make([]byte, 1024)
> i, err := conn.Read(buffer)
> if err != nil {
> break
> }
> buffer = buffer[0:i]
> log.Println("received from client: ", string(buffer))
> i, err = conn.Write(buffer)
> if err != nil {
> log.Println("error writing to client")
> } else {
> log.Printf("sent %d bytes\n", i)
> }
> }
> }
>
> func main() {
> listener, err := net.Listen("tcp", "
0.0.0.0:8080")
> if err != nil {
> log.Fatal("cannot create listener")
> }
> for {
> conn, err := listener.Accept()
> if err == nil {
> go connhandler(conn)
> } else {
> log.Println("error while accepting connection: ", err)
> }
> }
> }
>
>
> The output shows that sometimes two or more messages which were separately
> sent are received by one call of net.Conn.Read() and joined.
>
> 2012/09/12 02:27:41 reading from connection
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 received from server: ping 00ping 01ping 02
> 2012/09/12 02:27:41 reading from connection
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 received from server: ping 03
> 2012/09/12 02:27:41 reading from connection
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 received from server: ping 04ping 05ping 06ping 07
> 2012/09/12 02:27:41 reading from connection
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 sent 7 bytes
> 2012/09/12 02:27:41 received from server: ping 08ping 09
> 2012/09/12 02:27:41 reading from connection
>
>
>
> When I add a delay (~0.5sec) after sending each message everything is okay.
> Is there a way to make sure that .net.Conn.Read() receives only one message
> at once?
>
>
> Regards,
> Oliver