【问题标题】:golang tcp socket - process multiple messagesgolang tcp socket - 处理多条消息
【发布时间】:2016-09-07 10:44:50
【问题描述】:

我有这个 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)
  }
}

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

如何在无需关闭客户端连接(由客户端)的情况下从客户端发送多条消息?

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

感谢瓦莱里亚诺·科苏

【问题讨论】:

  • 正如答案所述,您必须以某种方式破坏您的消息。 TCP 本身是一种流协议,而不是基于数据包的协议。

标签: node.js sockets go tcp


【解决方案1】:

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

我在下面修改了你的代码。

转到服务器: 主包

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 客户端:

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');

  // 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');
});

【讨论】:

    【解决方案2】:

    io 包文档:https://golang.org/pkg/io/#Copy,Copy 函数复制直到遇到 EOF。

    您不手动发送 EOF,但关闭连接的客户端会这样做,因此 Copy 函数可以完成复制。

    您可以使用bufio 包来读取带有分隔符的字符串:

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

    在上述情况下,分隔符是换行符。您可以重复使用阅读器在其上重复调用 ReadString 以检索更多消息。

    【讨论】:

    • 谢谢 Nebril,没错,现在也按照 Tomaz 的解释工作。
    • @internet3 很高兴知道,请随时接受我或 Tomaz 的答案(在答案分数下打勾)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2014-10-11
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    相关资源
    最近更新 更多