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

这个应用演示如何使用 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
     }
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/81a5df2e3520774f9a241d5ae184ac6c.html