英文:
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 (
"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: "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
得分: 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('\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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论