使用 Go 和 WebSockets 构建实时聊天服务器(客户端)

原文地址:https://www.oschina.net/translate/build-a-realtime-chat-server-with-go-and-websockets?lang=chs&page=2#

构建客户端

如果没有漂亮的 UI,聊天应用程序将无法完成。 我们需要使用一些 HTML5 和 VueJS 来创建一个简单、干净的界面,再利用一些诸如 Materialize CSS 和 EmojiOn 的库来生成一些样式和表情符号。 在“public”目录中,创建一个名为“index.html”的新文件。

第一部分很基础。为了美观,我们也会放入一些样式表和字体。“style.css”是自定义的样式表,用于自定义一些内容。

<!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>

下一部分仅与接口相关,其中只包含一些用于选择用户名、发送消息和显示新的聊天信息的字段。与 VueJS 交互的细节超出本文的介绍范围,你可阅读此文档了解更多。

<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>

 

最后一步只需要导入所有需要的 JavaScript 库,包括 Vue、EmojiOne、jQuery 和 Materialize。我们需要 MD5 库获取来自 Gravatar 的头像 URL,这用 JavaScript 代码写出来就好理解了。最后导入 "app.js"。

<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>

然后在 "public" 目录下创建一个 "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;
}

客户端的最后一部分是 JavaScript 代码。在 "public" 目录下创建文件 "app.js"。

对于 VueJS 应用程序来说,一开始都是创建新的 Vue 对象。我们将它与 id 为 "#app" 的 div 绑定。这会让 div 内的所有东西与 Vue 实现共享作用域。下面定义一些变量。 

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
    },

Vue 提供了一个叫 "created" 的属性,这是一个函数,会在 Vue 实例刚刚创建时调用。这里非常适合对应用做一些设置工作。在这个示例中我们希望创建一个新的 WebSocket 连接与服务器连接,并创建一个处理器用于处理从服务器发送过来的消息。我们把新的 WebSocket 对象保存在 "data" 属性的 "ws" 变量中。 

 

"addEventListener()"方法接受一个用于处理传入消息的函数。我们期望所有消息都是 JSON 字符串,以便统一解析为一个对象字面量。然后我们可以用各个属性和 avater 头像一起组成漂亮的消息行。"gravatarURL()" 方法会在后面详述。我们用了一个叫 EmojiOne 的表情库来解析emoji 代码。"toImage()" 方法会把 emoji 代码转换为实际的图片。比如,如果你输入 ":robot:",它会被替换为一个机器人 emoji 表情图。

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" 属性可以定义各种函数,我们会在 VueJS 应用中使用这些函数。"send"方法用于向服务器发送消息。我们先确保消息不是空的,然后把消息组织成一个对象,再用"stringify"把它变成 JSON 字符串,以便服务器能正确解析。我们使用 jQuery 来处理传入消息中 HTML 和 JavaScript 中的特殊字符,以防止各种类型的注入攻击。

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"函数会确保用户在发送消息前输入 email 地址和用户名。一旦他们输入了这些信息,我们将 joined 设置为 "true",同时允许他们开始交谈。同样,我们会处理 HTML 和 JavaScript 的特殊字符。

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;
    },

最后一个函数是一个很好的辅助函数,用于从 Gravatar 获取头像。URL 的最后一段需要用户的 email 地址的 MD5 编码。MD5 是一种加密算法,它能隐藏 email 地址同时还能让 email 地址作为一个唯一标识来使用。

   
     gravatarURL: function(email) {
            return 'http://www.gravatar.com/avatar/' + CryptoJS.MD5(email);
        }
    }
});

 

运行应用程序

要运行该应用程序,请打开控制台窗口并确保进入应用程序的“src”目录中,然后运行以下命令。

$ go run main.go

接下来打开 Web 浏览器并导航到“http://localhost:8000”站点。  然后就会显示聊天屏幕,你可以在聊天屏幕中输入电子邮件和用户名。

如果要查看该应用多个用户之间的通信方式,只需另外打开一个浏览器标签页或窗口,然后导航到“http://localhost:8000”。 输入不同的电子邮件和用户名。然后轮流从两个窗口发送消息,这样就可以看到多个用户之间的通信方式了。

 

结论

这只是一个基本的聊天应用程序,你可以在此基础上进行更多的改进,添加更多的其他功能,并上传源代码,期待你能实现新用户加入或者离开聊天时的私人提醒或者通知。尽情创造吧,此处不设限!

我希望这篇文章对你有所帮助,并希望借此启发你使用 WebSockets 和 Go 开始创建自己的实时应用程序

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值