栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

一次与两个用户随机聊天(Socket.io)

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一次与两个用户随机聊天(Socket.io)

尽管由于过于模糊,我将结束这个问题,但由于过去几年我对websockets的使用过多,因此我有义务向您提供一些见解(尽管与socketio和nodejs的相关性不是很多)。我想一些简单的指南和相关链接可以为您提供帮助。所以首先

相关介绍的种类

您应该已经知道 Socket.ioWebSocket
实现。WebSockets(WS)允许服务器在需要时随时发送数据,只要连接仍处于打开状态即可,这与旧方法相反:客户端一直在查询,询问服务器上是否有更新。

您可以想象在聚会结束时一个女人和一个男人:“ 谢谢您,今晚,我很乐意有时再重复一遍。您能给我您的电话号码吗? ”-老人问。“
恩,你知道吗,最好给我你的,我保证会打电话给你! ”如果女孩要给他她的电话号码,他每天会打几次电话问她是否要去某个地方(
d否)。相反,她只有在她想离开而他会离开时才给他打电话。当然可以。我有点不高兴,但你知道了。女人是服务器,男人是客户。

重要的是要了解

(绝对基础,您应该知道此=>)当客户端连接到服务器时,应该为他提供一个html页面和一些javascript,以建立与WS服务器的连接。在您发布的代码中,
Express 用作http服务器。检查此示例以了解应如何为用户提供html&js。

您还将在大多数这些教程中注意到名称空间和房间。这些用于将用户分为子类别。一台服务器可以包含多个名称空间(默认情况下只有一个),每个名称空间可以包含多个房间。您可能不需要打扰命名空间,一个就足以满足您的情况。

接下来的事情,取自您的代码

io.on('connection', function (socket) {

重要的是要知道,这里的 套接字 基本上代表 一个连接的客户端 (在一个名称空间中,但可能在多个房间中)。您可以用它来做各种事情,最著名的是:

  • 在其上安装事件处理程序(这是您在调用时所做的
    socket.on(event, handler(data))
  • 向它发送事件
    socket.emit(event, data)
  • 发送广播事件给所有用户
    socket.broadcast.emit(event, data)
  • 加/从除去到/
    socket.join(room)
    socket.leave(room)
    分别。
  • 像使用 普通变量 一样使用它-将其存储在所需的位置,然后重用

您在代码中看到 numUsers 的定义了吗?这是所有客户端共享的全局变量,因为nodejs是 单线程的
。在示例中,它是在事件处理程序之一中递增的。认为我们可以使用类似的东西吗? 是的

我们可以定义全局变量,例如队列。如果需要,也可以问Q。关键是,它可以是用于存储 套接字 的数组,或者可以是当前不在聊天室中的客户端的数组。

在本节的最后,我想指出另一件事。 为 io* 对象(WS服务器)上发生的“连接”事件

io.on('connection', handler);
定义
事件处理程序 。每当客户端与您的WS服务器建立连接时(在您的情况下,是通过客户端浏览器中运行的javascript)触发的。该方法的参数是 套接字
,在该方法中,您应该为每个客户端添加事件侦听器(您已经在代码中进行了此操作,特别是处理事件“新消息”,“添加用户”,“键入”,“停止键入”和“断开连接”)。
* __

您需要什么活动

这实际上取决于您希望应用程序的复杂程度。我认为,最低要求是(请注意,您可以更改事件名称,但“断开连接”应保持为“断开连接”):

事件名称 ->给定的数据

服务器端处理的事件

  • 登录 ->用户名(应如何调用用户),如果要启用注册,则可以输入密码
  • 消息 ->文本(正在发送的消息内容)
  • 离开房间 ->房间名称
  • 断开

在客户端处理事件

  • 连接
  • 聊天开始 ->名称(第二个客户的姓名),房间(以便我们离开)
  • 聊天结束 ->如果您希望一次只允许一次聊天,则不需要数据。如果有多个聊天,您还应该包括哪个聊天已关闭
  • 断开

开始之前的最后一点

这只是一个粗略的草图。一路上有多个不同的十字路口,您选择哪种方式主要取决于您对应用程序的想法。如果您想同时打开多个聊天,则需要进行一些修改。如果您想让两个以上的人连接到同一聊天室,也是如此。在这里,我将向大家介绍最简单的情况,一次聊天,无需注册。从您的帖子来看,可能是您想要的。可能是错误的。

工作流程

用户在其网络浏览器中打开您的页面。您为他们提供html和javascript。javascript将开始与您的websocket服务器的新连接。另外,此时应定义所需事件的处理程序。建立连接后,将发生以下情况:

  1. 在服务器端

io.on('connection', handler)
将被解雇。仅安装适用于新套接字的处理程序,此时不执行任何其他操作。

  1. 在客户端

socket.on('connect',handler)
将被解雇。此时,客户端应将用户名存储在某处。如果没有,没问题。连接将在相当长的时间内保持活动状态。连接后,您可以随时调用
socket.emit('login',{'username':name)
(在下面的示例中,我设置了connected变量,该变量默认为false,但在建立连接后立即设置为true。)

从客户端发送 登录
事件后,服务器将其注册并保存到某处。可能性无穷无尽,在这种情况下,我将创建将socket.id映射到用户名的全局字典。之后,用户套接字应与另一个套接字配对或添加到队列中。因此,如果队列为空,只需将套接字附加到全局变量(它不必是数组,因为我们会将第一个可用的套接字配对在一起,但是您可能想要实现一些用户的历史记录,因此他们不会重新与同一个人建立联系)。如果队列不为空,我们从Q中拉出一个插座,并将其添加到同一房间。房间名称可以是随机的,也可以是您想要的任何名称,我将使用(socket1.id
+’#’+ socket2.id(如果您想在一次聊天中拥有更多用户,则必须进行更改)。

将他们都添加完后,您需要通知他们聊天已经开始,并向他们发送对方的名字。您将发出事件“聊天开始”。

客户将赶上活动并打开新窗口。此后,每当用户键入内容并将其发送时,客户端就会发出带有有效负载{‘message’:user_inserted_text}的事件’message’。服务器将在

.on('message'
处理程序中捕获它,并将其广播到房间。注意:

广播意味着将消息发送到其他人(除了启动该消息的套接字之外)。

注意:我现在对socketio代码真的很困惑。看看这个,告诉我,如果socket.rooms是一个数组还是一个对象(

socket.rooms[room]= room;
??为什么?)

为了避免处理这种不简单的代码,让我们创建另一个全局对象,

rooms
它将为我们存储房间名称。我们将在那里映射socket.id-> roomName。

因此,当出现消息时,我们可以通过致电获取房间名称

rooms[socket.id]
。然后我们广播这样的消息:

socket.broadcast.to(room).emit('message', data);

数据 是我们从发送方接收,因此对象{“文”:“一些不错的消息”}。然后您的同伴将收到(您不会)并显示它(发送时应显示它)。

因此,这样的聊天持续了一段时间,然后一个用户决定他要离开/与其他人聊天。他们将关闭窗口,客户将发出事件“离开房间”。服务器将捕获它,并将其发送给其对等方已断开连接的另一方。如果客户端断开连接,也会发生同样的情况。关闭所有内容后,将两个用户都添加到队列中(或一个,如果另一个已与服务器断开连接)。在我的代码中,我无法确保不会再次配对。那是为了OP进行编码(不难)。

因此,如果您读了这么多,应该得到一些实际的代码。尽管我说的是“ 实际” ,但实际上未经测试。但您知道,它应该像这样工作。

一些代码

客户端

var connected = false;var username = 'Faizan';var room = '';var socket = io('http://localhost');socket.on('connect', function (data) { // we are connected, should send our name    connected = true;    if (username) socket.emit('login', {'username' : username});});socket.on('chat start', function(data) {    room = data.room;    show_chat_window(data.name); // some method which will show chat window});socket.on('chat end', function(data) {    hide_chat_window(); // this will close chat window and alert user that the peer ended chat    socket.leave(room); // it's possible to leave from both server and client, hoever it is better to be done by the client in this case    room = '';});socket.on('disconnect', function(data) { // handle server/connection falling    console.log('Connection fell or your browser is closing.');});var send_message = function(text) { // method, which you will call when user hits enter in input field    if (connected) socket.emit('message', {'text': text});};var leave_chat = function() { // call this when user want to end current chat    if (connected) {        socket.emit('leave room');        socket.leave(room);        room = '';    }};

服务器端

不包括初始要求和html / js服务。仅包括全局定义和主要io处理程序。

var queue = [];    // list of sockets waiting for peersvar rooms = {};    // map socket.id => roomvar names = {};    // map socket.id => namevar allUsers = {}; // map socket.id => socketvar findPeerForLoneSocket = function(socket) {    // this is place for possibly some extensive logic    // which can involve preventing two people pairing multiple times    if (queue) {        // somebody is in queue, pair them!        var peer = queue.pop();        var room = socket.id + '#' + peer.id;        // join them both        peer.join(room);        socket.join(room);        // register rooms to their names        rooms[peer.id] = room;        rooms[socket.id] = room;        // exchange names between the two of them and start the chat        peer.emit('chat start', {'name': names[socket.id], 'room':room});        socket.emit('chat start', {'name': names[peer.id], 'room':room});    } else {        // queue is empty, add our lone socket        queue.push(socket);    }}io.on('connection', function (socket) {    console.log('User '+socket.id + ' connected');    socket.on('login', function (data) {        names[socket.id] = data.username;        allUsers[socket.id] = socket;        // now check if sb is in queue        findPeerForLoneSocket(socket);    });    socket.on('message', function (data) {        var room = rooms[socket.id];        socket.broadcast.to(room).emit('message', data);    });    socket.on('leave room', function () {        var room = rooms[socket.id];        socket.broadcast.to(room).emit('chat end');        var peerID = room.split('#');        peerID = peerID[0] === socket.id ? peerID[1] : peerID[0];        // add both current and peer to the queue        findPeerForLoneSocket(allUsers[peerID]);        findPeerForLoneSocket(socket);    });    socket.on('disconnect', function () {        var room = rooms[socket.id];        socket.broadcast.to(room).emit('chat end');        var peerID = room.split('#');        peerID = peerID[0] === socket.id ? peerID[1] : peerID[0];        // current socket left, add the other one to the queue        findPeerForLoneSocket(allUsers[peerID]);    });});

聚苯乙烯

上面的代码最后有点混乱。可以做得更好,我鼓励您做得比我更好。掌握了这些材料后,请逐步进行操作并尝试理解。我想我评论最多,即使不是全部。祝好运。

l

我什至都不惊讶。在这里看漫画



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/485018.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号