美文网首页
golang使用WebSocket创建即时聊天室

golang使用WebSocket创建即时聊天室

作者: 吃猫的鱼0 | 来源:发表于2018-01-08 15:31 被阅读0次

    WebSocket

    WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
    WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。

    WebSocket协议支持(在受控环境中运行不受信任的代码的)客户端与(选择加入该代码的通信的)远程主机之间进行全双工通信。用于此的安全模型是Web浏览器常用的基于原始的安全模式。 协议包括一个开放的握手以及随后的TCP层上的消息帧。 该技术的目标是为基于浏览器的、需要和服务器进行双向通信的(服务器不能依赖于打开多个HTTP连接(例如,使用XMLHttpRequest或iframe和长轮询))应用程序提供一种通信机制。

    websocket包

    github地址:

    https://github.com/gorilla/websocket

    获取:

    go get github.com/gorilla/websocket
    

    聊天室

    包结构

        --main
            --main.go
        --public 
            --index.html
            --app.js
            --style.css
    

    main.go

    package main
    
    import (
        "log"
        "net/http"
    
        "github.com/gorilla/websocket"
    )
    
    var clients = make(map[*websocket.Conn]bool) // connected clients
    var broadcast = make(chan Message)           // broadcast channel
    
    // Configure the upgrader
    var upgrader = websocket.Upgrader{
        CheckOrigin: func(r *http.Request) bool {
            return true
        },
    }
    
    // Define our message object
    type 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 messages
        go 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 returns
        defer ws.Close()
    
        // Register our new client
        clients[ws] = true
    
        for {
            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 connected
            for client := range clients {
                err := client.WriteJSON(msg)
                if err != nil {
                    log.Printf("error: %v", err)
                    client.Close()
                    delete(clients, client)
                }
            }
        }
    }
    

    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 emojis
    
                var 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);
            }
        }
    });
    

    style.css

    body {
        display: flex;
        min-height: 100vh;
        flex-direction: column;
    }
    
    main {
        flex: 1 0 auto;
    }
    
    #chat-messages {
        min-height: 10vh;
        height: 60vh;
        width: 100%;
        overflow-y: scroll;
    }
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Simple Chat</title>
    
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/css/materialize.min.css">
        <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/emojione/2.2.6/assets/css/emojione.min.css"/>
        <link rel="stylesheet" href="style.css">
    
    </head>
    <body>
    <header>
        <nav>
            <div class="nav-wrapper">
                <a href="/" class="brand-logo right">Simple Chat</a>
            </div>
        </nav>
    </header>
    <main id="app">
        <div class="row">
            <div class="col s12">
                <div class="card horizontal">
                    <div id="chat-messages" class="card-content" v-html="chatContent">
                    </div>
                </div>
            </div>
        </div>
        <div class="row" v-if="joined">
            <div class="input-field col s8">
                <input type="text" v-model="newMsg" @keyup.enter="send">
            </div>
            <div class="input-field col s4">
                <button class="waves-effect waves-light btn" @click="send">
                    <i class="material-icons right">chat</i>
                    Send
                </button>
            </div>
        </div>
        <div class="row" v-if="!joined">
            <div class="input-field col s8">
                <input type="email" v-model.trim="email" placeholder="Email">
            </div>
            <div class="input-field col s8">
                <input type="text" v-model.trim="username" placeholder="Username">
            </div>
            <div class="input-field col s4">
                <button class="waves-effect waves-light btn" @click="join()">
                    <i class="material-icons right">done</i>
                    Join
                </button>
            </div>
        </div>
    </main>
    <footer class="page-footer">
    </footer>
    <script src="https://unpkg.com/vue@2.1.3/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/emojione/2.2.6/lib/js/emojione.min.js"></script>
    <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/md5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>
    <script src="app.js"></script>
    </body>
    </html>
    

    资料参考:http://blog.csdn.net/wangshubo1989/article/details/78250790

    相关文章

      网友评论

          本文标题:golang使用WebSocket创建即时聊天室

          本文链接:https://www.haomeiwen.com/subject/orsbnxtx.html