package mainimport ( "log""net/http""github.com/gorilla/websocket")var clients = make(map[*websocket.Conn]bool) // connected clientsvar broadcast = make(chan Message) // broadcast channel// Configure the upgradervar upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { returntrue },}// Define our message objecttype Message struct { Email string`json:"email"` Username string`json:"username"` Message string`json:"message"`}func main() { // Create a simple file server fs := http.FileServer(http.Dir("../public")) http.Handle("/", fs) // Configure websocket route http.HandleFunc("/ws", handleConnections) // Start listening for incoming chat messagesgo handleMessages() // Start the server on localhost port 8000 and log any errors log.Println("http server started on :8000") err := http.ListenAndServe(":8000", nil) if err != nil { log.Fatal("ListenAndServe: ", err) }}func handleConnections(w http.ResponseWriter, r *http.Request) { // Upgrade initial GET request to a websocket ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Fatal(err) } // Make sure we close the connection when the function returnsdefer ws.Close() // Register our new client clients[ws] = truefor { var msg Message // Read in a new message as JSON and map it to a Message object err := ws.ReadJSON(&msg) if err != nil { log.Printf("error: %v", err) delete(clients, ws) break } // Send the newly received message to the broadcast channel broadcast <- msg }}func handleMessages() { for { // Grab the next message from the broadcast channel msg := <-broadcast // Send it out to every client that is currently connectedfor client := range clients { err := client.WriteJSON(msg) if err != nil { log.Printf("error: %v", err) client.Close() delete(clients, client) } } }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
app.js:
new Vue({ el: '#app', data: { ws: null, // Our websocket newMsg: '', // Holds new messages to be sent to the server chatContent: '', // A running list of chat messages displayed on the screen email: null, // Email address used for grabbing an avatar username: null, // Our username joined: false // True if email and username have been filled in }, created: function() { var self = this; this.ws = new WebSocket('ws://' + window.location.host + '/ws'); this.ws.addEventListener('message', function(e) { var msg = JSON.parse(e.data); self.chatContent += '<div class="chip">' + '<img src="' + self.gravatarURL(msg.email) + '">'// Avatar + msg.username + '</div>' + emojione.toImage(msg.message) + '<br/>'; // Parse emojisvar element = document.getElementById('chat-messages'); element.scrollTop = element.scrollHeight; // Auto scroll to the bottom }); }, methods: { send: function () { if (this.newMsg != '') { this.ws.send( JSON.stringify({ email: this.email, username: this.username, message: $('<p>').html(this.newMsg).text() // Strip out html } )); this.newMsg = ''; // Reset newMsg } }, join: function () { if (!this.email) { Materialize.toast('You must enter an email', 2000); return } if (!this.username) { Materialize.toast('You must choose a username', 2000); return } this.email = $('<p>').html(this.email).text(); this.username = $('<p>').html(this.username).text(); this.joined = true; }, gravatarURL: function(email) { return 'http://www.gravatar.com/avatar/' + CryptoJS.MD5(email); } }});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
index.html:
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>Simple Chat</title><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/css/materialize.min.css"><linkrel="stylesheet"href="https://fonts.googleapis.com/icon?family=Material+Icons"><linkrel="stylesheet"href="https://cdn.jsdelivr.net/emojione/2.2.6/assets/css/emojione.min.css"/><linkrel="stylesheet"href="/style.css"></head><body><header><nav><divclass="nav-wrapper"><ahref="/"class="brand-logo right">Simple Chat</a></div></nav></header><mainid="app"><divclass="row"><divclass="col s12"><divclass="card horizontal"><divid="chat-messages"class="card-content"v-html="chatContent"></div></div></div></div><divclass="row"v-if="joined"><divclass="input-field col s8"><inputtype="text"v-model="newMsg" @keyup.enter="send"></div><divclass="input-field col s4"><buttonclass="waves-effect waves-light btn" @click="send"><iclass="material-icons right">chat</i> Send </button></div></div><divclass="row"v-if="!joined"><divclass="input-field col s8"><inputtype="email"v-model.trim="email"placeholder="Email"></div><divclass="input-field col s8"><inputtype="text"v-model.trim="username"placeholder="Username"></div><divclass="input-field col s4"><buttonclass="waves-effect waves-light btn" @click="join()"><iclass="material-icons right">done</i> Join </button></div></div></main><footerclass="page-footer"></footer><scriptsrc="https://unpkg.com/[email protected]/dist/vue.min.js"></script><scriptsrc="https://cdn.jsdelivr.net/emojione/2.2.6/lib/js/emojione.min.js"></script><scriptsrc="https://code.jquery.com/jquery-2.1.1.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/md5.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script><scriptsrc="/app.js"></script></body></html>
请发表评论