2KB项目,专业的源码交易网站 帮助 收藏 每日签到

使用 Go 语言和 HTML5 WebSocket 构建一个 Web 聊天室

  • 时间:2019-01-23 18:43 编辑:2KB 来源:2KB.COM 阅读:385
  • 扫一扫,手机访问
  • 分享
摘要: 英文原文:Tec
英文原文:TechForce: Building a Web Chat with the Go programming language and HTML5 Websockets

这个应用演示如何使用 Google Go 语言和 HTML5 的 WebSocket 来实现一个简单的基于 Web 的聊天程序。

下图是聊天应用的截图:

Chat demo

你可输入 email 来加入聊天室,我们将从 Gravatar 上获取对应的用户名和头像,当你正在聊天时,你能在界面右侧看到聊天室其他人的姓名和头像。你可以输入信息来跟他们聊天。

现在,让我们来看看如何实现这么一个程序。

服务器端

首先我们需要一个名为 ActiveRoom 聊天室引擎作为整个应用的核心。该引擎将在下面的代码中定义,当程序主函数启动时将会初始化一个聊天室引擎实例并作为一个全局变量。

正在运行的实例用于维护所有 websocket 连接并处理收到的消息。一旦通过广播渠道接收到一个新的消息,它会将该消息发送到所有连接发送渠道。

Message 是服务器和客户端数据交互的基本数据类型,在这里我们定义了两个消息类型,一个是文本消息,另外一个是实时的用户在线状态。

type ActiveRoom struct {
     OnlineUsers map[string]*OnlineUser
     Broadcast   chan Message
     CloseSign   chan bool
}

type Message struct {
     MType       string
     TextMessage TextMessage
     UserStatus  UserStatus
}

func (this *ActiveRoom) run() {
     for {
          select {
          case b := <-this.Broadcast:
               for _, online := range this.OnlineUsers {
                    online.Send <- b
               }
          case c := <-this.CloseSign:
               if c == true {
                    close(this.Broadcast)
                    close(this.CloseSign)
                    return
               }
          }
     }
}


OnlineUser 类代表一个成功连接到聊天室的用户,它维护着 ActiveRoom 实例的指针、服务器和客户端之间的 websocket 连接,同时包括正在聊天的用户和 Go 的通讯渠道。

OnlineUser 定义了两个指针方法

PushToClient:
从发送渠道读取消息然后将这些消息通过 websocket 推送给客户端。

PullFromClient:
从客户端读取消息并发送到正在运行的 ActiveRoom 实例。

这两个方法使用 "for" 语句来等待新的消息,除非 websocket 连接中断。

type OnlineUser struct {
     InRoom     *ActiveRoom
     Connection *websocket.Conn
     UserInfo   *User
     Send       chan Message
}

func (this *OnlineUser) PullFromClient() {
     for {
          var content string
          err := websocket.Message.Receive(this.Connection, &content)

          if err != nil {
               return
          }

          m := Message{
               MType: TEXT_MTYPE,
               TextMessage: TextMessage{
                    UserInfo: this.UserInfo,
                    Time:     humanCreatedAt(),
                    Content:  content,
               },
          }
          this.InRoom.Broadcast <- m
     }
}

func (this *OnlineUser) PushToClient() {
     for b := range this.Send {
          err := websocket.JSON.Send(this.Connection, b)
          if err != nil {
               break
          }
     }
}


下面我们来看看程序流程,BuildConnection函数在 main 函数中被注册为 websocket 连接的处理器:

http.Handle("/chat", websocket.Handler(wscon.BuildConnection))


当有一个 websocket 连接请求,该函数将做一些初始化工作用于处理新的连接:

func BuildConnection(ws *websocket.Conn) {
     email := ws.Request().URL.Query().Get("email")
     onlineUser := &OnlineUser{
          InRoom:     runningActiveRoom,
          Connection: ws,
          Send:       make(chan Message, 256),
          UserInfo: &User{
               Email:    email,
               Name:     strings.Split(email, "@")[0],
               Gravatar: libs.UrlSize(email, 20),
          },
     }

     runningActiveRoom.OnlineUsers[email] = onlineUser

     m := Message{
          MType: STATUS_MTYPE,
          UserStatus: UserStatus{
               Users: runningActiveRoom.GetOnlineUsers(),
          },
     }

     runningActiveRoom.Broadcast <- m
     go onlineUser.PushToClient()
     onlineUser.PullFromClient()
     onlineUser.killUserResource()
}


客户端

最后一部分是客户端的实现,这是采用 JavaScript 实现的。它打开了一个新的 websocket 连接到聊天服务器,并注册回调函数用于处理来自服务器端的消息。你会发现当连接收到新的消息时,conn.onmessage 将被调用。现在你只需将接收到的消息交给对应的 JavaScript 函数去处理:

if (window["WebSocket"]) {
    conn = new WebSocket("ws://{{.WebSocketHost}}/chat?email={{.Email}}");
    conn.onopen = function() {};

    conn.onmessage = function(evt) {
         var data = JSON.parse(evt.data);
         switch(data.MType) {
              case "text_mtype":
                   addMessage(data.TextMessage)
                   break;
              case "status_mtype":
                   updateUsers(data.UserStatus)
                   break;
              default:
         }
    };

    conn.onerror = function() {
           errorMessage("<strong> An error just occured.<strong>")
    };

    conn.onclose = function() {
           errorMessage("<strong>Connection closed.<strong>")
    };
} else {
    errorMessage("Your browser does not support WebSockets.");
}


如果你对这个应用很感兴趣,你可以从这里获取整个应用的源码:gochatting.

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部