Anthony Hunt
Anthony Hunt

Reputation: 1610

go routine - why websocket reports the connection as closed?

I'm trying to create a client and a server using Go but for some reason the server reports the connection as "closed". As the code is trivial I can't think of anything wrong with my code. Any help is appreciated.

package main

import (
    log "github.com/golang/glog"
    "net/http"
    "golang.org/x/net/websocket"
    "time"
    "flag"
)

type server struct {
    payload chan string
}

// srv pushes the messages received via ws into srv.payload
func (srv *server) serve(ws *websocket.Conn) {
    go func() {
        var msg string
        if err := websocket.Message.Receive(ws, &msg); err != nil {
            log.Exit(err)
        }
        srv.payload <- msg
    }()
    return
}

// This example demonstrates a trivial client/ server.
func main() {
    flag.Parse()
    srv := server{payload: make(chan string, 10)}
    http.Handle("/echo", websocket.Handler(srv.serve))
    go func() {
        err := http.ListenAndServe(":12345", nil)
        if err != nil {
            log.Errorf("ListenAndServe: " + err.Error())
        }
    }()
    // give the server some time to start listening
    time.Sleep(3 *time.Second)
    //dial and test the response.
    ws, err := websocket.Dial("ws://localhost:12345/echo", "", "http://localhost/?x=45")
    if err != nil {
        log.Exit(err)
    }
    ms := "test"
    if err := websocket.Message.Send(ws, ms); err != nil {
        log.Exit(err)
    }
    msg := <-srv.payload
    if msg != ms{
        log.Errorf("msg %v is not %v", ms)
    }

}

Error

 t.go:21] read tcp 127.0.0.1:12345->127.0.0.1:43135: 

Edit: After some try and error I've found that if I remove the go routine from the serve method it works but it doesn't make sense to me. Any idea why it doesn't work when websocket.Message.Receive is in a separate go routine?

package main

import (
    log "github.com/golang/glog"
    "net/http"
    "golang.org/x/net/websocket"
    "time"
    "flag"
)

type server struct {
    payload chan string
}

// srv pushes the messages received via ws into srv.payload
func (srv *server) serve(ws *websocket.Conn) {
        var msg string
        if err := websocket.Message.Receive(ws, &msg); err != nil {
            log.Exit(err)
        }
        srv.payload <- msg 
    return
}

// This example demonstrates a trivial client/ server.
func main() {
    flag.Parse()
    srv := server{payload: make(chan string, 10)}

    go func() {
        http.Handle("/echo", websocket.Handler(srv.serve))
        err := http.ListenAndServe(":12345", nil)
        if err != nil {
            log.Errorf("ListenAndServe: " + err.Error())
        }
    }()
    // give the server some time to start listening
    time.Sleep(3 *time.Second)
    //dial and test the response.
    ws, err := websocket.Dial("ws://localhost:12345/echo", "", "http://localhost/?x=45")
    if err != nil {
        log.Exit(err)
    }
    ms := "test"
    if err := websocket.Message.Send(ws, ms); err != nil {
        log.Exit(err)
    }
    msg := <-srv.payload
    if msg != ms{
        log.Errorf("msg %v is not %v", ms)
    }

}

Upvotes: 1

Views: 1946

Answers (2)

Ajit Surendran
Ajit Surendran

Reputation: 787

Your main function quits and hence the gor dies. You need make your main func wait. See sync.WaitGroup and checkout functions like Add, Done, Wait.

Upvotes: 0

Thundercat
Thundercat

Reputation: 121199

The websocket server closes the connection when the handler returns.

Removing the Go routine is the correct fix.

Upvotes: 1

Related Questions