首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >异步消息golang

异步消息golang
EN

Stack Overflow用户
提问于 2015-02-12 04:42:36
回答 1查看 1.9K关注 0票数 0

我有一个golang服务器在做这样的事情: package main

代码语言:javascript
运行
复制
func main() {
    for {
        c := listener.Accept()
        go handle(c)
    }
}

...
func handle(c net.Conn) {
    m := readMessage(c)    // func(net.Conn)Message
    r := processMessage(m) //func(Message)Result
    sendResult(c, r)       // func(net.Conn,Result)
}

它同步地读写消息。我现在需要的是通过一个给定的开放连接异步发送消息,我知道一个通道可以被我迷路了。

这是我的想法:

代码语言:javascript
运行
复制
...
func someWhereElese(c chan Result) {
    // generate a message and a result
    r := createResultFromSomewhere()
    c <- r // send the result through the channel
}

并将我的句柄修改为使用相同的通道

代码语言:javascript
运行
复制
func handle(c net.Conn, rc chan Result) {
    m := readMessage(c)    // func(net.Conn)Message
    r := processMessage(m) //func(Message)Result
    //sendResult(c, r)       // func(net.Conn,Result)
    rc <- r
}

这就是我困惑的地方。

结果通道应该被创建,并且它应该有一个连接来发送它接收到的任何东西

代码语言:javascript
运行
复制
func doSend(c net.Con, rc chan Result) {
    r := rc          // got a result channel
    sendResult(c, r) // send it through the wire
}

但是应该在哪里创建这个通道呢?在主循环中?

代码语言:javascript
运行
复制
func main() {
    ...
    for {
        c := l.Accept()
        rc := make(chan Result)
        go doSend(c, rc)
    }
}

那读物呢?它应该进入它自己的频道/gorutine吗?如果我需要向n个客户端广播,我应该保留一个结果通道的切片吗?一段关系?

我有点困惑,但我觉得我已经很接近了。

EN

回答 1

Stack Overflow用户

发布于 2015-02-12 06:05:29

这个程序似乎解决了我眼前的问题

代码语言:javascript
运行
复制
package main

import (
    "bytes"
    "encoding/binary"
    "log"

    "net"
)

var rcs []chan int = make([]chan int,0)


func main() {
    a, e := net.ResolveTCPAddr("tcp", ":8082")
    if e != nil {
        log.Fatal(e)
    }
    l, e := net.ListenTCP("tcp", a)
    for {
        c, e := l.Accept()
        if e != nil {
            log.Fatal(e)
        }
        rc := make(chan int)
        go read(c, rc)
        go write(c, rc)
        rcs = append(rcs, rc)
        // simulate broacast
        log.Println(len(rcs))
        if len(rcs) > 5 {
            func() {
                for _, v := range rcs {
                    log.Println("sending")
                    select {
                    case v <- 34:
                        log.Println("done sending")
                    default:
                        log.Println("didn't send")
                    }
                }
            }()
        }
    }
}
func read(c net.Conn, rc chan int) {
    h := make([]byte, 2)
    for {
        _, err := c.Read(h)
        if err != nil {
            rc <- -1
        }
        var v int16
        binary.Read(bytes.NewReader(h[:2]), binary.BigEndian, &v)
        rc <- int(v)
    }
}
func write(c net.Conn, rc chan int) {
    for {
        r := <-rc
        o := []byte{byte(r * 2)}
        c.Write(o)
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28464098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档