I'm working on Cloud Server's networking thing using Go programming language. And I faced a problem with reading same TCPconn at the same time from different Goroutines.
Here is a simple example
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)
}
}
In this example console output always coming from 1st goroutine go Handle(conn)
...
How to make Read functionality from 2 Goroutines at the same time ?
Thanks
Start a single go routine to perform conn.Read(data) and put the result into a channel.
Then (concurrently, without waiting for the first go routine to finish) start multiple go routines to read from this channel.
You don't want to directly read from the conn concurrently from multiple go routine since it is not thread-safe (the fact that it runs, and only run only on a single go routine probably because your MAXGOPROCS == 1).
One way to do it is using io.MultiWriter
and io.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()
}
Ok so first of all. You're doing it wrong friend.
What you should do is create workers (pre-create), create channel and aggregate that channel with incoming connections. Than you should take that same connection inside of worker and handle it. On this way you'll get X concurrent workers that runs against your connections.
I went ahead and wrote you down one nice example of how to gracefully handle workers but did not had time to write down how to gracefully handle incoming connections. Never the less, you'll see what i mean.
http://play.golang.org/p/YkQVmBEWly
Hope this helps,