golang tcp socket – process multiple messages

huangapple go评论78阅读模式
英文:

golang tcp socket - process multiple messages

问题

我有这个Go的tcp套接字

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

接收一条消息,将其转换为字符串并显示,但如果客户端没有关闭连接,我无法像预期的那样在服务器上看到消息。

如何在不需要客户端关闭连接的情况下从客户端发送多条消息?

以下是Node.js中的客户端代码:

var net = require('net');

let packet = {
              Target: { Host: "", Port: "9000" },
              Name: { Family: "Newmarch", Personal: "Jan" },
              Email: [
                      { Kind: "home", Address: "jan@newmarch.name"},
                      { Kind: "work", Address: "j.newmarch@boxhill.edu.au"}
                     ]
}


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
英文:

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: "jan@newmarch.name"},
                      { Kind: "work", Address: "j.newmarch@boxhill.edu.au"}
                     ]
}


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

答案1

得分: 4

因为你正在获取一个持续的数据流,服务器需要知道如何分隔消息。一种方法是使用换行符。

我已经修改了你的代码如下。

Go服务器:

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

Node.js客户端:

var net = require('net');

let packet = {
              Target: { Host: "", Port: "9000" },
              Name: { Family: "Newmarch", Personal: "Jan" },
              Email: [
                      { Kind: "home", Address: "jan@newmarch.name"},
                      { Kind: "work", Address: "j.newmarch@boxhill.edu.au"}
                     ]
}


var client = new net.Socket();
client.connect(1200, '0.0.0.0', function() {
  console.log('Connected');
  
  // 发送10条消息
  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');
});

以上是翻译好的内容。

英文:

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 (
	&quot;bufio&quot;
	&quot;log&quot;
	&quot;net&quot;
)

func main() {

	l, err := net.Listen(&quot;tcp&quot;, &quot;:1200&quot;)
	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(&#39;\n&#39;)
				if err != nil {
					log.Printf(&quot;Error: %+v&quot;, err.Error())
					return
				}

				log.Println(&quot;Message:&quot;, string(message))
			}
		}(conn)
	}
}

Nodejs client:

var net = require(&#39;net&#39;);

let packet = {
              Target: { Host: &quot;&quot;, Port: &quot;9000&quot; },
              Name: { Family: &quot;Newmarch&quot;, Personal: &quot;Jan&quot; },
              Email: [
                      { Kind: &quot;home&quot;, Address: &quot;jan@newmarch.name&quot;},
                      { Kind: &quot;work&quot;, Address: &quot;j.newmarch@boxhill.edu.au&quot;}
                     ]
}


var client = new net.Socket();
client.connect(1200, &#39;0.0.0.0&#39;, function() {
  console.log(&#39;Connected&#39;);
  
  // Send 10 messages
  for(var i = 0; i &lt; 10; i++) {
  	client.write( (new Buffer(JSON.stringify(packet), &#39;UTF-8&#39;)) );
  	client.write(&#39;\n&#39;);
  }

  client.end();
  
});

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

client.on(&#39;close&#39;, function() {
  console.log(&#39;Connection closed&#39;);
});

答案2

得分: 1

io包的文档中可以看到:https://golang.org/pkg/io/#Copy,Copy函数会一直复制,直到遇到EOF。

你不需要手动发送EOF,而是客户端关闭连接时会发送EOF,所以Copy函数可以完成复制。

你可以使用bufio包来使用指定的分隔符读取字符串:

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

在上述情况中,分隔符是换行符。你可以重复使用该读取器来调用ReadString以获取更多的消息。

英文:

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(&#39;\n&#39;)

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.

huangapple
  • 本文由 发表于 2016年9月7日 18:44:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/39367765.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定