internet3
internet3

Reputation: 41

golang tcp socket - process multiple messages

I have this Go tcp socket

package main

import (
  "fmt"
  "io"
  "log"
  "net"
  "bytes"
)

func main() {

  l, err := net.Listen("tcp", ":1200")
  if err != nil {
    log.Fatal(err)
  }
  defer l.Close()
  for {

    conn, err := l.Accept()
    if err != nil {
      log.Fatal(err)
    }

    go func(c net.Conn) {

      var buf bytes.Buffer
      io.Copy(&buf, c)
      fmt.Println("total size:", buf.Len())
      s := buf.String()
      println(s)

      c.Close()
    }(conn)
  }
}

accept a message, transform it to string and display it, but if the connection is not closed by the client I am not able to see the message showed on the server as expected

How is possible to send multiple message from the client without the need to close the client connection (by the client) ?

Here the client in NodeJs

var net = require('net');

let packet = {
              Target: { Host: "", Port: "9000" },
              Name: { Family: "Newmarch", Personal: "Jan" },
              Email: [
                      { Kind: "home", Address: "[email protected]"},
                      { Kind: "work", Address: "[email protected]"}
                     ]
}


var client = new net.Socket();
client.connect(1200, '0.0.0.0', function() {
  console.log('Connected');
  client.write( (new Buffer(JSON.stringify(packet), 'UTF-8')) );
  client.end();
  //client.write('\n');
});

client.on('data', function(data) {
  console.log('Received: ' + data);
  client.destroy();
});

client.on('close', function() {
  console.log('Connection closed');
});

Thanks valeriano cossu

Upvotes: 3

Views: 4831

Answers (2)

user4101925
user4101925

Reputation:

Because you are getting a constant stream of data the server needs to know how to seperate messages. One way of doing that is using a new line character.

I have revised your code below.

Go server: package main

import (
    "bufio"
    "log"
    "net"
)

func main() {

    l, err := net.Listen("tcp", ":1200")
    if err != nil {
        log.Fatal(err)
    }
    defer l.Close()
    for {

        conn, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }

        go func(c net.Conn) {
            for {
                message, err := bufio.NewReader(conn).ReadString('\n')
                if err != nil {
                    log.Printf("Error: %+v", err.Error())
                    return
                }

                log.Println("Message:", string(message))
            }
        }(conn)
    }
}

Nodejs client:

var net = require('net');

let packet = {
              Target: { Host: "", Port: "9000" },
              Name: { Family: "Newmarch", Personal: "Jan" },
              Email: [
                      { Kind: "home", Address: "[email protected]"},
                      { Kind: "work", Address: "[email protected]"}
                     ]
}


var client = new net.Socket();
client.connect(1200, '0.0.0.0', function() {
  console.log('Connected');

  // Send 10 messages
  for(var i = 0; i < 10; i++) {
    client.write( (new Buffer(JSON.stringify(packet), 'UTF-8')) );
    client.write('\n');
  }

  client.end();

});

client.on('data', function(data) {
  console.log('Received: ' + data);
  client.destroy();
});

client.on('close', function() {
  console.log('Connection closed');
});

Upvotes: 4

Nebril
Nebril

Reputation: 3273

From the io package documentation: https://golang.org/pkg/io/#Copy , the Copy function copies until it encounters EOF.

You don't send EOF manually but the client closing the connection does that, so the Copy function can finish the copying.

You can use bufio package to read strings with your delimiter:

line, err := bufio.NewReader(conn).ReadString('\n')

In the above case, the delimiter is new line character. You can reuse the reader to repeatedly call ReadString on it to retrieve more messages.

Upvotes: 1

Related Questions