20725


実は以前にも似たような質問をしているのですが・・・  
[GolangでWebsocketで非同期でReceive,
Sendをする](https://ja.stackoverflow.com/questions/12087/golang%E3%81%A7websocket%E3%81%A7%E9%9D%9E%E5%90%8C%E6%9C%9F%E3%81%A7receive-
send%E3%82%92%E3%81%99%E3%82%8B)

下記のコードを実行すると`Sender Error use of closed network connection...`と表示されます。  
sync.WaitGroupを使って全ての`ws`へのSendが終わるまで待って、もし、`err !=
nil`ならconnectionの一覧として使っている`conns`から削除しています。

このエラーを解決するにはどうすればいいのでしょうか? また なぜ起こるのでしょうか?

[code]

    
    package main
    
    import (
        "fmt"
        "golang.org/x/net/websocket"
        "net/http"
        "sync"
    )
    
    type Message struct {
        Name    string
        Message string
    }
    
    var conns = make(map[*websocket.Conn]bool)
    
    var wg sync.WaitGroup
    
    func chat_receiver(ws *websocket.Conn, msg *Message) {
        fmt.Println("Chat Receiver")
        conns[ws] = true
        err := websocket.JSON.Receive(ws, msg)
        fmt.Println("Received data:", msg)
        if err != nil {
            fmt.Println("Receiver Error:", err)
            ws.Close()
            delete(conns, ws)
        }
        fmt.Println("Data received")
    
    }
    
    func chat_sender(msg *Message) {
        fmt.Println("Chat Sender")
        fmt.Println(conns)
        for ws, _ := range conns {
            wg.Add(1)
            go func(ws *websocket.Conn) {
                fmt.Println(ws)
                err := websocket.JSON.Send(ws, msg)
                fmt.Println("Message sent")
                if err != nil {
                    fmt.Println("Sender Error:", err)
                    ws.Close()
                    delete(conns, ws)
                }
                defer wg.Done()
            }(ws)
            wg.Wait()
        }
    }
    
    func handler(ws *websocket.Conn) {
        var msg Message
        chat_receiver(ws, &msg;)
        chat_sender(&msg;)
    }
    
    func main() {
        http.Handle("/", http.FileServer(http.Dir(".")))
        http.Handle("/chat", websocket.Handler(handler))
        fmt.Println("serve on localhost:4283")
        err := http.ListenAndServe(":4283", nil)
        if err != nil {
            fmt.Println(err)
        }
    }
    
    
    
[/code]


CC BY-SA 3.0
2016-01-07T13:25:21.827
20719
2016-01-07T23:56:04.860
2017-04-13T12:52:38.920
-1
5246
question
go websocket goroutine
Goのwebsocketで起きたuse of closed network connectionについて


golang の websocket を使ったサーバを書く場合、accept から close されるまでは1つのハンドラ内で生き続ける必要があります。

上記のコードだと conns の数だけ回ってしまうとせっかく accept したソケットがハンドラを抜けて閉じられてしまいます。

以下に websocket を使った chat のコードを示しておきます。

<https://github.com/mattn/gopher/blob/master/cmd/chat/chat.go>


CC BY-SA 3.0
2016-01-07T23:56:04.860
20725
2016-01-07T23:56:04.860
440
20719
answer