Created
September 24, 2015 19:54
-
-
Save maksadbek/631ca7165f9fb2688b69 to your computer and use it in GitHub Desktop.
Websocket echo server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"log" | |
"net/http" | |
"time" | |
"github.com/gorilla/websocket" | |
) | |
var addr = flag.String("addr", "localhost:4321", "http service address") | |
const ( | |
// Time allowed to write a message to the peer. | |
writeWait = 10 * time.Second | |
// Time allowed to read the next pong message from the peer. | |
pongWait = 60 * time.Second | |
// Send pings to peer with this period. Must be less than pongWait. | |
pingPeriod = (pongWait * 9) / 10 | |
// Maximum message size allowed from peer. | |
maxMessageSize = 512 | |
) | |
var upgrader = websocket.Upgrader{ | |
ReadBufferSize: 1024, | |
WriteBufferSize: 1024, | |
} | |
// connection is an middleman between the websocket connection and the hub. | |
type connection struct { | |
// The websocket connection. | |
ws *websocket.Conn | |
// Buffered channel of outbound messages. | |
send chan []byte | |
} | |
// readPump pumps messages from the websocket connection to the hub. | |
func (c *connection) readPump() { | |
defer func() { | |
c.ws.Close() | |
}() | |
c.ws.SetReadLimit(maxMessageSize) | |
c.ws.SetReadDeadline(time.Now().Add(pongWait)) | |
c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil }) | |
for { | |
mt, message, err := c.ws.ReadMessage() | |
if err != nil { | |
break | |
} | |
log.Println("recv: ", string(message)) | |
err = c.ws.WriteMessage(mt, message) | |
if err != nil { | |
break | |
} | |
} | |
} | |
// write writes a message with the given message type and payload. | |
func (c *connection) write(mt int, payload []byte) error { | |
c.ws.SetWriteDeadline(time.Now().Add(writeWait)) | |
return c.ws.WriteMessage(mt, payload) | |
} | |
// writePump pumps messages from the hub to the websocket connection. | |
func (c *connection) writePump() { | |
ticker := time.NewTicker(pingPeriod) | |
defer func() { | |
ticker.Stop() | |
c.ws.Close() | |
}() | |
for { | |
select { | |
case message, ok := <-c.send: | |
if !ok { | |
c.write(websocket.CloseMessage, []byte{}) | |
return | |
} | |
if err := c.write(websocket.TextMessage, message); err != nil { | |
return | |
} | |
case <-ticker.C: | |
if err := c.write(websocket.PingMessage, []byte{}); err != nil { | |
return | |
} | |
} | |
} | |
} | |
// serverWs handles websocket requests from the peer. | |
func serveWs(w http.ResponseWriter, r *http.Request) { | |
if r.Method != "GET" { | |
http.Error(w, "Method not allowed", 405) | |
return | |
} | |
ws, err := upgrader.Upgrade(w, r, nil) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
c := &connection{send: make(chan []byte, 256), ws: ws} | |
go c.writePump() | |
c.readPump() | |
} | |
func main() { | |
flag.Parse() | |
log.SetFlags(0) | |
http.HandleFunc("/ws", serveWs) | |
http.Handle("/", http.FileServer(http.Dir("wsstatic/"))) | |
err := http.ListenAndServe(*addr, nil) | |
if err != nil { | |
log.Fatal("ListenAndServe: ", err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment