如何使用Socket.IO编写聊天应用程序

2020-10-01 科技 124阅读

我们将首先通过查看客户端代码。所有聊天互动都有HomeView处理,首先需要在 /public/js/models/main.js中定义HomeModel。

var HomeModel = Backbone.Model.extend({
 defaults: {
   // Backbone collection for users
   onlineUsers: new UserCollection(),

   // Backbone collection for user chats, 初始化一个预定义聊天模型
   userChats: new ChatCollection([
     new ChatModel({sender: '', message: 'Chat Server v.1'})
   ])
 },

 // 添加一个新用户到 onlineUsers collection
 addUser: function(username) {
   this.get('onlineUsers').add(new UserModel({name: username}));
 },

 // 从onlineUsers collection中移除一个用户
 removeUser: function(username) {
   var onlineUsers = this.get('onlineUsers');
   var u = onlineUsers.find(function(item) {
         return item.get('name') == username;
       });

   if (u) {
     onlineUsers.remove(u);
   }
 },

 // 添加一个新的聊天到 userChats collection
 addChat: function(chat) {
   this.get('userChats').add(new ChatModel({sender: chat.sender, message: chat.message}));
 },
});

我们利用Backbone集合来侦听集合变化。这些集合的更新会直接由视图自动反映出来。接下来,需要在/public/index.html中定义home模板。


聊天客户端

接下来, 让我们来定义 我们的 Socket.IO 聊天客户端 。 客户端 与服务器端的通信,主要通过发送消息和监听通知 来完成。 这些通知 触发事件 与所述控制器 进行通信。请参阅 下面 /public/ JS / socketclient.js的代码 。

var ChatClient = function(options) {
 // 避免冲突
 var self = this;

 // app event bus
 self.vent = options.vent;

 // server hostname replace with your server's hostname eg: http://localhost
 self.hostname = 'http://chatfree.herokuapp.com';

 // connects to the server
 self.connect = function() {
   // connect to the host
   self.socket = io.connect(self.hostname);

   // set responseListeners on the socket
   self.setResponseListeners(self.socket);
 }

 // send login message
 self.login = function(name) {
   self.socket.emit('login', name);
 }

 // send chat message
 self.chat = function(chat) {
   self.socket.emit('chat', chat);
 }

 self.setResponseListeners = function(socket) {
   // handle messages from the server
   socket.on('welcome', function(data) {
     // request server info
     socket.emit('onlineUsers');

     self.vent.trigger('loginDone', data);
   });

   socket.on('loginNameExists', function(data) {
     self.vent.trigger('loginNameExists', data);
   });

   socket.on('loginNameBad', function(data) {
     self.vent.trigger('loginNameBad', data);
   });

   socket.on('onlineUsers', function(data) {
     console.log(data);
     self.vent.trigger('usersInfo', data);
   });

   socket.on('userJoined', function(data) {
     self.vent.trigger('userJoined', data);
   });

   socket.on('userLeft', function(data) {
     self.vent.trigger('userLeft', data);
   });

   socket.on('chat', function(data) {
     self.vent.trigger('chatReceived', data);
   });
 }
}

使用Socket.IO可以非常简单的发送和接受通信数据,上面的代码中,使用了下面的两个方法

socket.emit(message, [callback])  向服务器端发送消息

socket.on(message, callback)      用于接收来自服务器的消息

让我们来看一下他们的通信协议

主控制器

客户端最后一步,主控制器,它控制了VIEW,MODEL和socket客户端,代码在/public/js/main.js中

var MainController = function() {
 var self = this;

 // Event Bus for socket client
 self.appEventBus = _.extend({}, Backbone.Events);
 // Event Bus for Backbone Views
 self.viewEventBus = _.extend({}, Backbone.Events);

 // initialize function
 self.init = function() {
   // create a chat client and connect
   self.chatClient = new ChatClient({vent: self.appEventBus});
   self.chatClient.connect();

   // create our views, place login view inside container first.
   self.loginModel = new LoginModel();
   self.containerModel = new ContainerModel({
     viewState: new LoginView({
       vent: self.viewEventBus,
       model: self.loginModel
     })
   });
   self.containerView = new ContainerView({model: self.containerModel});
   self.containerView.render();
 };

 // View Event Bus Message Handlers
 self.viewEventBus.on('login', function(name) {
   // socketio login
   self.chatClient.login(name);
 });

 self.viewEventBus.on('chat', function(chat) {
   // socketio chat
   self.chatClient.chat(chat);
 });

 // Socket Client Event Bus Message Handlers

 // triggered when login success
 self.appEventBus.on('loginDone', function() {
   self.homeModel = new HomeModel();
   self.homeView  = new HomeView({vent: self.viewEventBus, model: self.homeModel});

   // set viewstate to homeview
   self.containerModel.set('viewState', self.homeView);
 });

 // triggered when login error due to bad name
 self.appEventBus.on('loginNameBad', function(name) {
   self.loginModel.set('error', 'Invalid Name');
 });

 // triggered when login error due to already existing name
 self.appEventBus.on('loginNameExists', function(name) {
   self.loginModel.set('error', 'Name already exists');
 });

 // triggered when client requests users info
 // responds with an array of online users.
 self.appEventBus.on('usersInfo', function(data) {
   var onlineUsers = self.homeModel.get('onlineUsers');
   var users = _.map(data, function(item) {
     return new UserModel({name: item});
   });

   onlineUsers.reset(users);
 });

 // triggered when a client joins the server
 self.appEventBus.on('userJoined', function(username) {
   self.homeModel.addUser(username);
   self.homeModel.addChat({sender: '', message: username + ' joined room.'});
 });

 // triggered when a client leaves the server
 self.appEventBus.on('userLeft', function(username) {
   self.homeModel.removeUser(username);
   self.homeModel.addChat({sender: '', message: username + ' left room.'});
 });

 // triggered when chat receieved
 self.appEventBus.on('chatReceived', function(chat) {
   self.homeModel.addChat(chat);
 });
}

最后,我们需要定义一个MainController入口,调用init方法,代码位于/public/js/main.js中

聊天服务器端

应用程序的最后一部分是聊天服务器。它主要负责维护在线用户列表,广播聊天消息。比如,首先,服务器会给一个新的客户的连接请求命名,然后通过刚刚建立的socket,连接事件handlers。socket handler处理如下事件:    socket.on(message, callback)  - 在收到新邮件时回调函数被调用。消息可以是任何类型的数据,这取决于发送的消息。    socket.on('disconnect', callback) - 当socket断开连接时候,回调函数被调用。    socket.emit(message, args) - 通过socket发送消息。     socket.broadcast.send(message, args)  - 广播信息到除发送者之外的所有socket。现在,我们已经看到了handler socket是如何工作的。首先,需要在/scripts/chatserver.js中定义一个用户模型 :

总结

我们已经看到了如何使用Backbone和Socket.IO构建一个简单的聊天应用程序。还有很多没有在本文中涉及的Socket.IO性能,例如rooms和namespaces。通过这篇文章,我们可以看出使用Socket.IO很容易的在客户端和服务器端交换消息。

声明:你问我答网所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系fangmu6661024@163.com