为了账号安全,请及时绑定邮箱和手机立即绑定

Go:服务器应该阻塞,直到收到来自客户端的消息

Go:服务器应该阻塞,直到收到来自客户端的消息

Go
隔江千里 2021-11-29 19:31:36
我正在构建一些服务器/客户端应用程序Go(语言对我来说是新的)。我搜索了很多并阅读了一大堆不同的例子,但仍有一件事我找不到。假设我有一个服务器客户端启动并运行。客户端会向服务器发送某种消息,反之亦然。编码和解码是由包完成的gob。这个例子不是我的应用程序,它只是一个简单的例子:package mainimport (    "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)}这工作得很好,但我想服务器阻塞,直到收到新的消息,所以我可以把接收流程内infinite for loop内goroutine。类似的东西: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)}
查看完整描述

2 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

gob 解码器会阻塞,直到它读取完整的消息或出现错误。问题中的读取循环按原样工作。



查看完整回答
反对 回复 2021-11-29
?
白衣染霜花

TA贡献1796条经验 获得超10个赞

向原始 tcp 流添加长度标头。


这意味着,在发送实际负载之前向服务器发送一个 4 字节长度的标头信息。在服务器端读取 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

您可能知道客户端参考我认为的服务器端源。


查看完整回答
反对 回复 2021-11-29
  • 2 回答
  • 0 关注
  • 229 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信