Skip to content

Commit 84770ad

Browse files
committed
0 parents  commit 84770ad

File tree

2 files changed

+204
-0
lines changed

2 files changed

+204
-0
lines changed

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
run: clean example
2+
./example
3+
4+
include $(GOROOT)/src/Make.inc
5+
6+
TARG=example
7+
GOFILES=\
8+
main.go\
9+
10+
include $(GOROOT)/src/Make.cmd

main.go

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"http"
6+
"log"
7+
"template"
8+
"websocket"
9+
)
10+
11+
type message struct {
12+
text []byte
13+
}
14+
15+
type client struct {
16+
messages chan message
17+
ws *websocket.Conn
18+
}
19+
20+
type hub struct {
21+
messages chan message
22+
subscribes chan *client
23+
unsubscribes chan *client
24+
}
25+
26+
func (h *hub) run() {
27+
clients := make(map[*client]bool)
28+
for {
29+
select {
30+
case c := <-h.subscribes:
31+
clients[c] = true
32+
case c := <-h.unsubscribes:
33+
if clients[c] {
34+
delete(clients, c)
35+
close(c.messages)
36+
}
37+
case m := <-h.messages:
38+
for c := range clients {
39+
select {
40+
case c.messages <- m:
41+
default:
42+
delete(clients, c)
43+
close(c.messages)
44+
go c.ws.Close()
45+
}
46+
}
47+
}
48+
}
49+
}
50+
51+
func (c *client) shutdown() {
52+
h.unsubscribes <- c
53+
c.ws.Close()
54+
}
55+
56+
func (c *client) reader() {
57+
defer c.shutdown()
58+
for {
59+
text := make([]byte, 256)
60+
n, err := c.ws.Read(text)
61+
if err != nil {
62+
break
63+
}
64+
h.messages <- message{text[:n]}
65+
}
66+
}
67+
68+
func (c *client) writer() {
69+
defer c.shutdown()
70+
for m := range c.messages {
71+
_, err := c.ws.Write(m.text)
72+
if err != nil {
73+
break
74+
}
75+
}
76+
}
77+
78+
var addr = flag.String("addr", ":8080", "http service address")
79+
80+
var h = hub{make(chan message), make(chan *client), make(chan *client)}
81+
82+
func main() {
83+
flag.Parse()
84+
go h.run()
85+
http.HandleFunc("/", homeHandler)
86+
http.Handle("/ws", websocket.Handler(wsHandler))
87+
if err := http.ListenAndServe(*addr, nil); err != nil {
88+
log.Fatal("ListenAndServe:", err)
89+
}
90+
}
91+
92+
func wsHandler(ws *websocket.Conn) {
93+
c := &client{make(chan message, 256), ws}
94+
h.subscribes <- c
95+
go c.writer()
96+
c.reader()
97+
}
98+
99+
func homeHandler(c http.ResponseWriter, req *http.Request) {
100+
homeTempl.Execute(c, req.Host)
101+
}
102+
103+
var homeTempl = template.Must(template.New("home").Parse(`
104+
<html>
105+
<head>
106+
<title>Chat Example</title>
107+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
108+
<script type="text/javascript">
109+
$(function() {
110+
111+
var conn;
112+
var msg = $("#msg");
113+
var log = $("#log");
114+
115+
function appendLog(msg) {
116+
var d = log[0]
117+
var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight;
118+
msg.appendTo(log)
119+
if (doScroll) {
120+
d.scrollTop = d.scrollHeight - d.clientHeight;
121+
}
122+
}
123+
124+
$("#form").submit(function() {
125+
if (!conn) {
126+
return false;
127+
}
128+
if (!msg.val()) {
129+
return false;
130+
}
131+
conn.send(msg.val());
132+
msg.val("");
133+
return false
134+
});
135+
136+
if (window["WebSocket"]) {
137+
conn = new WebSocket("ws://{{$}}/ws");
138+
conn.onclose = function(evt) {
139+
appendLog($("<div><b>Connection closed.</b></div>"))
140+
}
141+
conn.onmessage = function(evt) {
142+
appendLog($("<div/>").text(evt.data))
143+
}
144+
} else {
145+
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"))
146+
}
147+
});
148+
</script>
149+
<style type="text/css">
150+
html {
151+
overflow: hidden;
152+
}
153+
154+
body {
155+
overflow: hidden;
156+
padding: 0;
157+
margin: 0;
158+
width: 100%;
159+
height: 100%;
160+
background: gray;
161+
}
162+
163+
#log {
164+
background: white;
165+
margin: 0;
166+
padding: 0.5em 0.5em 0.5em 0.5em;
167+
position: absolute;
168+
top: 0.5em;
169+
left: 0.5em;
170+
right: 0.5em;
171+
bottom: 3em;
172+
overflow: auto;
173+
}
174+
175+
#form {
176+
padding: 0 0.5em 0 0.5em;
177+
margin: 0;
178+
position: absolute;
179+
bottom: 1em;
180+
left: 0px;
181+
width: 100%;
182+
overflow: hidden;
183+
}
184+
185+
</style>
186+
</head>
187+
<body>
188+
<div id="log"></div>
189+
<form id="form">
190+
<input type="submit" value="Send" />
191+
<input type="text" id="msg" size="64"/>
192+
</form>
193+
</body>
194+
</html> `))

0 commit comments

Comments
 (0)