Go - 从多个读取器的TCP连接读取数据

时间:2015-07-18 15:07:49

标签: networking tcp go network-programming

我正在使用Go编程语言处理云服务器的网络事务。 我遇到了一个问题,从不同的Goroutines同时读取相同的TCPconn

这是一个简单的例子

package main

import (
    "fmt"
    "net"
)

func main() {
    addr, _ := net.ResolveTCPAddr("tcp", ":8888")
    listener, _ := net.ListenTCP("tcp", addr)

    for {
        conn, err := listener.AcceptTCP()
        if err != nil {
            fmt.Println(err)
            return
        }
        go Handle(conn) // output always coming from here
        go Handle(conn)
    }
}

func Handle(conn *net.TCPConn) {
    data := make([]byte, 1024)
    fmt.Println("Ok")
    for {
        len_data, err := conn.Read(data)
        fmt.Println(err)
        fmt.Println(len_data)
    }
}

在此示例中,控制台输出始终来自第一个goroutine go Handle(conn) ...

如何同时从2个Goroutines进行读取功能?

由于

3 个答案:

答案 0 :(得分:1)

一种方法是使用io.MultiWriterio.Pipe

func main() {
    var wg sync.WaitGroup
    r := strings.NewReader(hello)
    pr1, pw1 := io.Pipe()
    pr2, pw2 := io.Pipe()
    pr3, pw3 := io.Pipe()
    mw := io.MultiWriter(pw1, pw2, pw3)

    wg.Add(4)
    go process(&wg, 0, pr1)
    go process(&wg, 1, pr2)
    go process(&wg, 2, pr3)
    go func() {
        io.Copy(mw, r)
        pw1.Close()
        pw2.Close()
        pw3.Close()
        wg.Done()
    }()

    wg.Wait()
}

playground

答案 1 :(得分:0)

启动单个go例程以执行conn.Read(data)并将结果放入通道。

然后(同时,无需等待第一个例行程序完成)启动多个例程以从该频道读取。

你不想直接从多个go例程中读取conn,因为它不是线程安全的(事实上它运行,并且只能在单个go例程上运行,可能是因为你的MAXGOPROCS == 1)

答案 2 :(得分:-1)

好的,首先。你做错了朋友。

您应该做的是创建工作人员(预创建),创建频道并使用传入连接聚合该频道。比你应该在工人内部采取相同的连接并处理它。通过这种方式,您将获得针对您的连接运行的X并发工作程序。

我继续向你写了一个很好的例子,说明如何优雅地处理工人,但没有时间写下如何优雅地处理传入的连接。从来没有,你会明白我的意思。

http://play.golang.org/p/YkQVmBEWly

希望这有帮助,