Created
June 16, 2013 14:46
-
-
Save andrewytliu/5792278 to your computer and use it in GitHub Desktop.
Websocket chatroom in Go
This file contains hidden or 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
<html> | |
<head> | |
<title>HashGreen</title> | |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> | |
<script type="text/javascript"> | |
$(function() { | |
var conn, msg = $("#msg"), log = $("#log"); | |
$("#form").submit(function() { | |
if (!conn) return false; | |
if (!msg.val()) return false; | |
conn.send(msg.val()); | |
msg.val(""); | |
return false; | |
}); | |
conn = new WebSocket("ws://{{$}}/ws"); | |
conn.onclose = function(e) { | |
log.append($("<div><b>Connection closed.</b></div>")); | |
} | |
conn.onmessage = function(e) { | |
log.append($("<div/>").text(e.data)); | |
} | |
}); | |
</script> | |
<style type="text/css"> | |
html { | |
overflow: hidden; | |
} | |
body { | |
overflow: hidden; | |
padding: 0; | |
margin: 0; | |
width: 100%; | |
height: 100%; | |
background: #252525; | |
font-family: 'Lato', sans-serif; | |
} | |
#log { | |
border-radius: 20px; | |
background: #FFF; | |
margin: 5em; | |
padding: 0.5em; | |
overflow: auto; | |
} | |
#form { | |
padding: 5px; | |
margin-left: 5em; | |
margin-right: 5em; | |
overflow: hidden; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="log"></div> | |
<form id="form"> | |
<input type="text" id="msg" size="50" /> | |
<input type="submit" value="Send!" /> | |
</form> | |
</body> | |
</html> |
This file contains hidden or 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 ( | |
"code.google.com/p/go.net/websocket" | |
"log" | |
"net/http" | |
"text/template" | |
) | |
type Connection struct { | |
ws *websocket.Conn | |
send chan string | |
} | |
func (c *Connection) ReadLoop() { | |
for { | |
var m string | |
err := websocket.Message.Receive(c.ws, &m) | |
if err != nil { | |
log.Println("Read conn:", err) | |
break | |
} | |
pool.broadcast <- m | |
} | |
c.ws.Close() | |
} | |
func (c *Connection) WriteLoop() { | |
for m := range c.send { | |
err := websocket.Message.Send(c.ws, m) | |
if err != nil { | |
log.Println("Write conn:", err) | |
break | |
} | |
} | |
c.ws.Close() | |
} | |
func NewConnection(ws *websocket.Conn) { | |
c := &Connection{send: make(chan string, 256), ws: ws} | |
pool.connect <- c | |
defer func() { pool.disconnect <- c }() | |
go c.WriteLoop() | |
c.ReadLoop() | |
} | |
type Pool struct { | |
connections map[*Connection]bool | |
broadcast chan string | |
connect chan *Connection | |
disconnect chan *Connection | |
} | |
func (p *Pool) Run() { | |
for { | |
select { | |
case c := <-p.connect: | |
p.connections[c] = true | |
log.Println("New connection in:", c.ws.LocalAddr()) | |
case c := <-p.disconnect: | |
delete(p.connections, c) | |
log.Println("Disconnected:", c.ws.LocalAddr()) | |
case m := <-p.broadcast: | |
log.Println("Broadcasting:", m) | |
for c := range p.connections { | |
select { | |
case c.send <- m: | |
default: | |
delete(p.connections, c) | |
close(c.send) | |
go c.ws.Close() | |
} | |
} | |
} | |
} | |
} | |
var pool = Pool{ | |
connections: make(map[*Connection]bool), | |
broadcast: make(chan string), | |
connect: make(chan *Connection), | |
disconnect: make(chan *Connection), | |
} | |
var tmpl = template.Must(template.ParseFiles("home.html")) | |
func main() { | |
go pool.Run() | |
http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) { | |
tmpl.Execute(res, req.Host) | |
}) | |
http.Handle("/ws", websocket.Handler(NewConnection)) | |
log.Println("Starting the server...") | |
if err := http.ListenAndServe(":3000", nil); err != nil { | |
log.Fatal("Serve: ", err) | |
} | |
log.Println("Server started") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment