异步消息golang

时间:2015-02-11 20:42:36

标签: asynchronous go channel goroutine

我有一个golang服务器做这样的事情:     包主要

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

同步读取和写入消息。我现在需要的是通过给定的开放连接异步发送消息,我知道我可以使用某个频道丢失。

这是我的想法:

...
func someWhereElese(c chan Result) {
    // generate a message and a result
    r := createResultFromSomewhere()
    c <- r // send the result through the channel
}

修改我的句柄以使用相同的频道

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
}

这就是我的困惑所在。

应该创建结果通道,并且它应该具有连接发送它接收的任何内容的连接

func doSend(c net.Con, rc chan Result) {
    r := rc          // got a result channel
    sendResult(c, r) // send it through the wire
}

但该频道应该在哪里创建?在主循环?

func main() {
    ...
    for {
        c := l.Accept()
        rc := make(chan Result)
        go doSend(c, rc)
    }
}

阅读怎么样?它应该进入它自己的频道/ gorutine吗? 如果我需要向n个客户端广播,我应该保留一小部分结果通道吗?一段连接?

我在这里很困惑,但我觉得我很亲密。

1 个答案:

答案 0 :(得分:1)

这个程序似乎解决了我的直接问题

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