我正在尝试创建一个程序,该程序将通过大猩猩网络套接字连接到多个服务器。我目前有一个程序,该程序将遍历服务器地址列表并创建一个新的goroutine,该例程将创建自己的Websocket.conn并处理读写操作。
问题在于,每次创建新的goroutine时,以前的goroutine都会被阻止,只有最后一个goroutine才能继续。我相信这是因为大猩猩网络套接字库阻止了每个gorotutine,但我可能会误会。
我尝试在服务器列表迭代器中放置一个计时器,每个goroutine都将正常运行,但是在用另一个地址创建新goroutine的那一刻,以前的goroutine被阻止了。
我的代码的相关部分:
在我的main.go
for _, server := range servers {
go control(ctx, server, port)
}
在control()
func control(ctx context.Context, server, port string) {
url := url.URL{
Scheme: "ws",
Host: server + ":" + port,
Path: "",
}
conn, _, err := websocket.DefaultDialer.Dial(url.String(), nil)
if err != nil {
panic(err)
}
defer conn.Close()
go sendHandler(ctx, conn)
go readHandler(ctx, conn)
}
readHandler(ctx context.Context, conn *websocket.Con) {
for {
_, p, err := conn.ReadMessage(); if err != nil {
panic(err)
}
select {
case <-ctx.Done():
goto TERM
default:
// do nothing
}
}
TERM:
// do termination
}
sendHandler(ctx context.Context, conn *websocket.Con) {
for _, msg := range msges {
err = conn.WriteMessage(websocket.TextMessage, msg)
if err != nil {
panic(err)
}
}
<-ctx.Done()
}
我删除了添加等待组和其他不必要代码段的部分。
所以我期望有3n个goroutine运行(其中n是服务器的数量)而没有阻塞,但是现在我只看到3个goroutine正在运行,这是服务器列表的最后一次迭代所调用的。 / p>
谢谢!
编辑14/06/2019:
我花了一些时间编写一个小的工作示例,在该示例中并未发生错误-没有一个线程相互阻塞。我仍然不确定是什么原因造成的,但这是我的一个小示例:
main.go
package main
import (
"context"
"fmt"
"os"
"time"
"os/signal"
"syscall"
"sync"
"net/url"
"github.com/gorilla/websocket"
)
func main() {
servers := []string{"5555","5556", "5557"}
comms := make(chan os.Signal, 1)
signal.Notify(comms, os.Interrupt, syscall.SIGTERM)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
for _, server := range servers {
wg.Add(1)
go control(server,
ctx,
&wg)
}
<-comms
cancel()
wg.Wait()
}
func control(server string, ctx context.Context, wg *sync.WaitGroup) {
fmt.Printf("Started control for %s\n", server)
url := url.URL {
Scheme: "ws",
Host: "0.0.0.0" + ":" + server,
Path: "",
}
conn, _, err := websocket.DefaultDialer.Dial(url.String(), nil)
if err != nil {
panic(err)
}
defer conn.Close()
var localwg sync.WaitGroup
localwg.Add(1)
go sendHandler(ctx, conn, &localwg, server)
localwg.Add(1)
go readHandler(ctx, conn, &localwg, server)
<- ctx.Done()
localwg.Wait()
wg.Done()
return
}
func sendHandler(ctx context.Context, conn *websocket.Conn, wg *sync.WaitGroup, server string) {
for i := 0; i < 50; i++ {
err := conn.WriteMessage(websocket.TextMessage, []byte("ping"))
if err != nil {
panic(err)
}
fmt.Printf("sent msg to %s\n", server)
time.Sleep(1 * time.Second)
}
<- ctx.Done()
wg.Done()
}
func readHandler(ctx context.Context, conn *websocket.Conn, wg *sync.WaitGroup, server string) {
for {
select {
case <- ctx.Done():
wg.Done()
return
default:
_, p, err := conn.ReadMessage()
if err != nil {
wg.Done()
fmt.Println("done")
}
fmt.Printf("Got [%s] from %s\n", string(p), server)
}
}
}
我分别在5555、5556和5557上的服务器上使用dpallot的simple-websocket-server对它进行了测试。
答案 0 :(得分:0)
这部分代码导致了问题:
conn, _, err := websocket.DefaultDialer.Dial(url.String(), nil)
if err != nil {
panic(err)
}
defer conn.Close()
go sendHandler(ctx, conn)
go readHandler(ctx, conn)
您创建连接,推迟连接,开始另外两个goroutine,然后结束函数。由于您的推迟,功能端会关闭插座。