Go:服务器应该阻塞,直到收到来自客户端的消息
Go: Server should block until a message from the client is received
我正在 Go
中构建一些 server/client 应用程序(该语言对我来说是新的)。我进行了很多搜索并阅读了一大堆不同的示例,但仍然找不到一件事。假设我有一个服务器客户端启动并且 运行。客户端将向服务器发送某种消息,反之亦然。编解码由包gob
.
完成
这个例子不是我的应用程序,它只是一个简单的例子:
package main
import (
"bytes"
"encoding/gob"
"fmt"
"log"
)
type Message struct {
Sender string
Receiver string
Command uint8
Value int64
}
func (message *Message) Set(sender string, receiver string, command uint8, value int64) *Message {
message.Sender = sender
message.Receiver = receiver
message.Command = command
message.Value = value
return message
}
func main() {
var network bytes.Buffer // Stand-in for a network connection
enc := gob.NewEncoder(&network) // Will write to network.
dec := gob.NewDecoder(&network) // Will read from network.
message := new(Message).Set("first", "second", 10, -1)
err := enc.Encode(*message) // send message
if err != nil {
log.Fatal("encode error:", err)
}
var m Message
err = dec.Decode(&m) // receice message
if err != nil {
log.Fatal("decode error:", err)
}
fmt.Printf("%q %q %d %d\n", m.Sender, m.Receiver, m.Command, m.Value)
}
这很好用,但我希望服务器在收到新消息之前阻塞,这样我就可以将接收进程放在 goroutine
中的 infinite for loop
中。
类似的东西:
for {
// The server blocks HERE until a message from the client is received
fmt.Println("Received message:")
// Decode the new message
var m Message
err = dec.Decode(&m) // receice message
if err != nil {
log.Fatal("decode error:", err)
}
fmt.Printf("%q %q %d %d\n", m.Sender, m.Receiver, m.Command, m.Value)
}
向原始 tcp 流添加长度 header。
也就是说,在发送实际负载之前,发送一个4-bytes-length-header信息给服务器。并在服务器端读取 4 个字节,分配缓冲区,完整读取消息,最后解码。
假设你有一个 tcp 连接 conn,在服务器端我们可以有:
func getInt(v []byte) int {
var r uint
r = 0
r |= uint(v[0]) << 24
r |= uint(v[1]) << 16
r |= uint(v[2]) << 8
r |= uint(v[3]) << 0
return int(r)
}
buf := make([]byte, 4)
_, err := io.ReadFull(conn, buf)
if err != nil {
return
}
length := getInt(buf)
buf = make([]byte, length)
_, err = io.ReadFull(conn, buf)
if err != nil {
return
}
//do gob decode from `buf` here
你可能知道客户端引用我认为的服务器端来源。
gob 解码器会阻塞,直到它读取完整消息或出现错误。问题中的读取循环按原样工作。
我正在 Go
中构建一些 server/client 应用程序(该语言对我来说是新的)。我进行了很多搜索并阅读了一大堆不同的示例,但仍然找不到一件事。假设我有一个服务器客户端启动并且 运行。客户端将向服务器发送某种消息,反之亦然。编解码由包gob
.
这个例子不是我的应用程序,它只是一个简单的例子:
package main
import (
"bytes"
"encoding/gob"
"fmt"
"log"
)
type Message struct {
Sender string
Receiver string
Command uint8
Value int64
}
func (message *Message) Set(sender string, receiver string, command uint8, value int64) *Message {
message.Sender = sender
message.Receiver = receiver
message.Command = command
message.Value = value
return message
}
func main() {
var network bytes.Buffer // Stand-in for a network connection
enc := gob.NewEncoder(&network) // Will write to network.
dec := gob.NewDecoder(&network) // Will read from network.
message := new(Message).Set("first", "second", 10, -1)
err := enc.Encode(*message) // send message
if err != nil {
log.Fatal("encode error:", err)
}
var m Message
err = dec.Decode(&m) // receice message
if err != nil {
log.Fatal("decode error:", err)
}
fmt.Printf("%q %q %d %d\n", m.Sender, m.Receiver, m.Command, m.Value)
}
这很好用,但我希望服务器在收到新消息之前阻塞,这样我就可以将接收进程放在 goroutine
中的 infinite for loop
中。
类似的东西:
for {
// The server blocks HERE until a message from the client is received
fmt.Println("Received message:")
// Decode the new message
var m Message
err = dec.Decode(&m) // receice message
if err != nil {
log.Fatal("decode error:", err)
}
fmt.Printf("%q %q %d %d\n", m.Sender, m.Receiver, m.Command, m.Value)
}
向原始 tcp 流添加长度 header。
也就是说,在发送实际负载之前,发送一个4-bytes-length-header信息给服务器。并在服务器端读取 4 个字节,分配缓冲区,完整读取消息,最后解码。
假设你有一个 tcp 连接 conn,在服务器端我们可以有:
func getInt(v []byte) int {
var r uint
r = 0
r |= uint(v[0]) << 24
r |= uint(v[1]) << 16
r |= uint(v[2]) << 8
r |= uint(v[3]) << 0
return int(r)
}
buf := make([]byte, 4)
_, err := io.ReadFull(conn, buf)
if err != nil {
return
}
length := getInt(buf)
buf = make([]byte, length)
_, err = io.ReadFull(conn, buf)
if err != nil {
return
}
//do gob decode from `buf` here
你可能知道客户端引用我认为的服务器端来源。
gob 解码器会阻塞,直到它读取完整消息或出现错误。问题中的读取循环按原样工作。