zoukankan      html  css  js  c++  java
  • go语言从零学起(四) -- 基于martini和gorilla实现的websocket聊天实例

    如果只是想了解chat的实现方式,在gorilla和revel框架里面都有完整的chat实例可以提供参考。本篇讲解的是,如何基于martini实现websocket的聊天。

    配置步骤:

    1 已经安装了go命令,配置了GOPATH

    2 安装gorilla/websocket

    go get github.com/gorilla/websocket

    3 安装martini

    go get github.com/go-martini/martini
    

    项目文件列表

    $GOPATH/demo/home.html
    $GOPATH/demo/martini_ws.go

    home.html 代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <title>Chat Example</title>
    <script type="text/javascript">
    window.onload = function () {
        var conn;
        var msg = document.getElementById("msg");
        var log = document.getElementById("log");
    
        function appendLog(item) {
            var doScroll = log.scrollTop === log.scrollHeight - log.clientHeight;
            log.appendChild(item);
            if (doScroll) {
                log.scrollTop = log.scrollHeight - log.clientHeight;
            }
        }
    
        document.getElementById("form").onsubmit = function () {
            if (!conn) {
                return false;
            }
            if (!msg.value) {
                return false;
            }
            conn.send(msg.value);
            msg.value = "";
            return false;
        };
    
        if (window["WebSocket"]) {
            conn = new WebSocket("ws://{{$}}/ws");
            conn.onclose = function (evt) {
                var item = document.createElement("div");
                item.innerHTML = "<b>Connection closed.</b>";
                appendLog(item);
            };
            conn.onmessage = function (evt) {
                var messages = evt.data.split('
    ');
                for (var i = 0; i < messages.length; i++) {
                    var item = document.createElement("div");
                    item.innerText = messages[i];
                    appendLog(item);
                }
            };
        } else {
            var item = document.createElement("div");
            item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
            appendLog(item);
        }
    };
    </script>
    <style type="text/css">
    html {
        overflow: hidden;
    }
    
    body {
        overflow: hidden;
        padding: 0;
        margin: 0;
         100%;
        height: 100%;
        background: gray;
    }
    
    #log {
        background: white;
        margin: 0;
        padding: 0.5em 0.5em 0.5em 0.5em;
        position: absolute;
        top: 0.5em;
        left: 0.5em;
        right: 0.5em;
        bottom: 3em;
        overflow: auto;
    }
    
    #form {
        padding: 0 0.5em 0 0.5em;
        margin: 0;
        position: absolute;
        bottom: 1em;
        left: 0px;
         100%;
        overflow: hidden;
    }
    
    </style>
    </head>
    <body>
    <div id="log"></div>
    <form id="form">
        <input type="submit" value="Send" />
        <input type="text" id="msg" size="64"/>
    </form>
    </body>
    </html>

    martini_ws.go代码

    package main
    
    import (
        "fmt"
        "github.com/go-martini/martini"
        "github.com/gorilla/websocket"
        "log"
        "net/http"
        "text/template"
    )
    
    const (
        readBufferSize  = 1024
        writeBufferSize = 1024
    )
    
    type Client struct {
        conn     *websocket.Conn
        messages chan []byte
    }
    
    var clients map[*Client]bool // 存储所有的链接
    var broadcast chan []byte    // 广播聊天的chan
    var addClients chan *Client  // 新链接进来的chan
    
    func (c *Client) readPump() {
        for {
            _, message, err := c.conn.ReadMessage()
            if err != nil {
                if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
                    log.Printf("error: %v", err)
                }
                break
            }
            fmt.Printf("receive message is :%s
    ", message)
            broadcast <- message
        }
    }
    
    func (c *Client) writePump() {
        for {
            select {
            case message := <-c.messages:
                fmt.Printf("send message is :%s
    ", message)
                c.conn.WriteMessage(1, message)
            }
        }
    }
    
    func manager() {
    
        clients = make(map[*Client]bool)
        broadcast = make(chan []byte, 10)
        addClients = make(chan *Client)
    
        for {
            select {
            case message := <-broadcast:
                for client := range clients {
                    select {
                    case client.messages <- message:
                    default:
                        close(client.messages)
                        delete(clients, client)
                    }
                }
            case itemClient := <-addClients:
                clients[itemClient] = true
            }
        }
    }
    
    func main() {
    
        var homeTemplate = template.Must(template.ParseFiles("home.html"))
    
        m := martini.Classic()
    
        m.Get("/", func(res http.ResponseWriter, req *http.Request) {
    
            res.Header().Set("Content-Type", "text/html; charset=utf-8")
            homeTemplate.Execute(res, req.Host)
        })
    
        m.Get("/ws", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
            conn, err := websocket.Upgrade(res, req, nil, readBufferSize, writeBufferSize)
            if err != nil {
                log.Println(err)
                return
            }
            client := &Client{conn: conn, messages: make(chan []byte, 5)}
            addClients <- client
            go client.writePump()
            client.readPump()
        })
    
        go manager()
    
        m.RunOnAddr(":3010")
        //m.Run()
    
    }

    按照上面的步骤建好文件,就可以运行了。m.RunOnAddr 可以改成你需要的端口

    执行命令:

    go run martini_ws.go
    

    在浏览器输入 http://localhost:3010 就能访问你本机的聊天服务了

     参考地址

    https://github.com/patcito/martini-gorilla-websocket-chat-example

      

  • 相关阅读:
    生手和FinallyJane一起学习ASP.NET
    使用eclipse 初学java
    关于C#中用access做数据库,使用like语句的问题(转)
    VSS (Visual Source Safe 2005) 用法详解(转)
    mysql 字符集问题之我见
    mysqli的预处理功能使用
    兼容IE和Firefox
    linux下netsnmp 已经安装,为什么没有 snmpwalk和snmpget
    ? PHP WBEM
    安装cacti时提示错误
  • 原文地址:https://www.cnblogs.com/cornor/p/6178507.html
Copyright © 2011-2022 走看看