Skip to content

Instantly share code, notes, and snippets.

@yusuke024
Last active August 29, 2015 14:15
Show Gist options
  • Save yusuke024/66aa8e49099d317cc260 to your computer and use it in GitHub Desktop.
Save yusuke024/66aa8e49099d317cc260 to your computer and use it in GitHub Desktop.
Go Web Socket implementation
package main
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"golang.org/x/net/websocket"
)
var (
addr = flag.String("p", "80", "websocket port")
stdinBroadcaster = NewReadBroadcaster(os.Stdin)
)
type ReadBroadcaster struct {
ws []io.Writer
}
func NewReadBroadcaster(r io.Reader) *ReadBroadcaster {
rb := new(ReadBroadcaster)
rb.ws = make([]io.Writer, 0)
go func() {
br := bufio.NewReader(r)
for {
line, _, _ := br.ReadLine()
for i, w := range rb.ws {
_, err := w.Write(line)
if err != nil {
rb.ws = append(rb.ws[:i], rb.ws[i+1:]...)
}
}
}
}()
return rb
}
func (rb *ReadBroadcaster) Subscribe() io.ReadCloser {
pr, pw := io.Pipe()
rb.ws = append(rb.ws, pw)
return pr
}
func main() {
flag.Parse()
http.Handle("/", websocket.Handler(broadcastHandler))
done := make(chan bool, 0)
go func() {
err := http.ListenAndServe(":"+*addr, nil)
log.Fatal(err)
close(done)
}()
fmt.Println("server's starting on port " + *addr)
<-done
}
func broadcastHandler(ws *websocket.Conn) {
req := ws.Request()
fmt.Println("incoming connection:", req.URL, req.RemoteAddr)
done := make(chan bool)
go func() {
defer close(done)
for {
_, err := ws.Read(nil)
if err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
}
}()
r := stdinBroadcaster.Subscribe()
defer r.Close()
go io.Copy(ws, r)
<-done
fmt.Println("connection closed:", req.URL, req.RemoteAddr)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment