新人提问:Nodejs node-chat是如何解决多连接阻塞的问题的?

新人提问:Nodejs node-chat是如何解决多连接阻塞的问题的?

node chat源码解读中提到,node-chat采用了long poll模型来与服务器通信。 但是根据HTTP规范,浏览器不能与同一服务端建立超过2个HTTP连接,超过2个的连接会被浏览器阻塞。 而node-chat多开后仍能正常通信,是怎样实现的?

2 回复

要理解 node-chat 是如何解决多连接阻塞问题的,我们需要先了解其背后的机制。node-chat 使用了长轮询(long polling)模型来实现客户端与服务器之间的实时通信。长轮询是一种模拟服务器推送的技术,通过客户端发起一个长时间的 HTTP 请求到服务器,服务器保持连接打开直到有新数据可用或超时。

尽管浏览器对同一域名下的并发连接数量有限制(通常是2个),但 node-chat 可以通过使用多个子域名或者不同的端口来绕过这个限制。此外,现代浏览器通常允许更多的并发连接数,具体取决于浏览器的实现和版本。

示例代码

以下是一个简单的长轮询示例,展示了客户端如何向服务器发起请求,并等待服务器响应:

客户端代码(JavaScript)

function longPoll() {
    fetch('/poll', {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json'
        }
    })
    .then(response => response.json())
    .then(data => {
        console.log('New message:', data.message);
        // 重新发起长轮询
        longPoll();
    });
}

// 开始长轮询
longPoll();

服务器代码(Node.js)

const express = require('express');
const app = express();

let messages = [];

app.get('/poll', (req, res) => {
    if (messages.length > 0) {
        // 如果有新消息,立即返回
        res.json({ message: messages.shift() });
    } else {
        // 否则保持连接打开,直到有新消息
        req.setTimeout(30000); // 设置超时时间为30秒
        res.on('close', () => {
            console.log('Connection closed without response');
        });
        setTimeout(() => {
            res.json({ message: null }); // 返回空消息
        }, 30000);
    }
});

app.post('/send', (req, res) => {
    const { message } = req.body;
    messages.push(message);
    res.send('Message sent');
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

解释

  1. 客户端:使用 fetch 发起一个 GET 请求到 /poll 路径。如果服务器有新消息,它会立即返回;否则,客户端将等待直到服务器返回消息或超时。
  2. 服务器:当接收到 GET 请求时,检查是否有新消息。如果有,则返回消息;如果没有,则保持连接打开一段时间(例如30秒)。超时后,服务器返回一个空消息,客户端重新发起请求。

多连接处理

为了支持多个并发连接,可以通过配置多个子域名或端口来绕过浏览器的并发连接限制。例如,可以配置 chat1.example.comchat2.example.com,每个子域名可以处理独立的连接池。

总之,node-chat 通过长轮询模型和合理的连接管理策略,成功实现了多用户的实时通信,即使在浏览器连接数有限的情况下也能正常工作。


node-chat项目使用了WebSocket协议来处理多个客户端连接的问题。WebSocket是一种在单个TCP连接上进行全双工通信的协议。与传统的HTTP请求-响应模式不同,WebSocket允许服务器主动向客户端推送数据,从而解决了HTTP长轮询(Long Polling)模型中的限制。

示例代码

以下是一个简单的WebSocket服务器和客户端示例:

WebSocket服务器代码 (使用ws库)

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', ws => {
    console.log('Client connected');

    ws.on('message', message => {
        console.log(`Received: ${message}`);
        // 将消息广播给所有连接的客户端
        wss.clients.forEach(client => {
            if (client !== ws && client.readyState === WebSocket.OPEN) {
                client.send(message);
            }
        });
    });

    ws.on('close', () => {
        console.log('Client disconnected');
    });
});

WebSocket客户端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Client</title>
</head>
<body>
    <script>
        const socket = new WebSocket('ws://localhost:8080');

        socket.onopen = () => {
            console.log('Connected to server');
            socket.send('Hello Server');
        };

        socket.onmessage = (event) => {
            console.log(`Message from server: ${event.data}`);
        };

        socket.onclose = () => {
            console.log('Disconnected from server');
        };
    </script>
</body>
</html>

解释

  • WebSocket:通过WebSocket协议,客户端可以与服务器建立一个持久的连接,从而避免了HTTP协议的连接限制。
  • Broadcasting Messages:当一个客户端发送消息时,服务器会将该消息广播给所有其他连接的客户端。
  • Long Polling vs WebSocket:虽然node-chat文档中提到了Long Polling,但实际项目可能使用WebSocket来提供更高效的实时通信能力。

通过使用WebSocket,node-chat能够支持多个客户端的同时连接,并且不会受到浏览器限制的影响。

回到顶部