Nodejs中socket如何同时读写?
Nodejs中socket如何同时读写?
有一个server,同时实现如下功能: 1.读取客户端发送的消息写数据库。 2.读取数据一个表的数据发送个客户端。
不是等待读完再写或者写完再读,而是同时进行。
如果其他语言实现的话可能2个线程一直循环做不同的事情,
请问node.js中如何实现。
非常感谢。
在Node.js中,由于其单线程、事件驱动的特性,我们通常使用异步编程来实现并发操作。对于您的需求(同时读取客户端消息并写入数据库,以及从数据库读取数据并发送给客户端),可以利用回调函数、Promise或async/await语法来实现。
以下是一个简单的示例,展示如何使用net
模块创建服务器,并同时处理读写操作。这里以一个基本的TCP服务器为例,该服务器将监听客户端消息,同时定期向客户端发送数据。
const net = require('net');
// 创建一个TCP服务器
const server = net.createServer((socket) => {
console.log('Client connected');
// 定义一个定时器,每隔一段时间向客户端发送数据
const sendInterval = setInterval(() => {
socket.write('Hello from server\n');
}, 5000);
// 处理客户端发送的数据
socket.on('data', (data) => {
console.log(`Received: ${data.toString()}`);
// 将接收到的数据写入到数据库(这里简化为打印)
writeDataToDatabase(data);
});
// 处理客户端断开连接
socket.on('end', () => {
clearInterval(sendInterval);
console.log('Client disconnected');
});
});
// 模拟将数据写入数据库的函数
function writeDataToDatabase(data) {
console.log(`Writing to database: ${data.toString()}`);
}
server.listen(3000, () => {
console.log('Server listening on port 3000');
});
解释
- 服务器创建:使用
net.createServer()
创建一个TCP服务器。 - 定时发送:通过
setInterval()
设置一个定时器,每隔5秒向客户端发送一次消息。 - 处理数据:当接收到客户端发送的数据时,触发
socket.on('data')
事件。在这个事件处理程序中,我们打印接收到的数据,并模拟将其写入数据库。 - 数据库写入:这里的
writeDataToDatabase()
只是一个简单的函数,用于打印接收到的数据。实际应用中,您可以替换为实际的数据库操作代码。 - 客户端断开:当客户端断开连接时,清除定时器并打印日志。
这种方法利用了Node.js的非阻塞I/O模型,使得读写操作可以并发执行,而不会阻塞主线程。
两个线程跑就是系统在切换线程执行, 实际上是一个线程在 CPU 上跑. Node 里 JS 执行是单线程的, 但通过回调会调用 JS 引擎以外的代码, 而在触发回调前执行的代码是可以同时多个线程在跑的, 也有交替执行的效果.
比如下面的代码, req
和 req2
就是交替打印的:
var http, options, req, req2;
http = require(“http”);
options = {
hostname: ‘www.qq.com’,
port: 80,
path: ‘/’,
method: ‘GET’
};
req = http.request(options, function(res) {
res.setEncoding(“utf8”);
return res.on(“data”, function(chunk) {
return console.log(“req…”);
});
});
req2 = http.request(options, function(res) {
res.setEncoding(“utf8”);
return res.on(“data”, function(chunk) {
return console.log(“req2…”);
});
});
req.end();
req2.end();
谢谢 ” 两个线程跑就是系统在切换线程执行, 实际上是一个线程在 CPU 上跑. “
这个我是明白的,但是node.js不是很熟悉
我的程序结构应该是这样的:
var server = net.createServer( function(c) {
c.on(‘data’, function(data) {
//do something
//write db
});
//1
});
function serverStart () {
server.listen(SERVER_PORT, function() {
console.log(‘server bound’);
});
}
serverStart();
我想在这个主流程之外同时有个循环,主动给客户端发包
while true {
//read from db
//write to current client
}
我是想了解,这段代码放在那个位置?
现在的实现是在//1位置放了个: setInterval(SomeFunc, 1000);
但是这个不是很符合我的需求(考虑到一次调用没完成到时间又跑一次,需要一些标记变量来判断是否执行之类的)。
请问如何实现,谢谢。
“读取数据一个表的数据”的回调函数应该是异步的,“读取客户端发送的消息写数据库”的回调函数也是异步的,所以两者之间的发生时间是没有先后顺序的。
在Node.js中,你可以使用事件驱动和非阻塞I/O模型来实现同时读写socket。这里的关键在于利用异步编程技术,例如回调函数、Promise或async/await。为了实现你的需求,可以使用net
模块创建TCP服务器,并通过事件处理程序来同时读写socket。
下面是一个简单的示例,展示如何使用net
模块实现上述功能:
const net = require('net');
const { promisify } = require('util');
// 创建服务器
const server = net.createServer((socket) => {
console.log('Client connected');
// 设置socket的错误监听器
socket.on('error', (err) => {
console.error('Socket error:', err);
});
// 用于处理从数据库读取数据的操作
const readFromDatabase = async () => {
// 假设这是一个异步操作,从数据库读取数据
const data = await promisify(readDataFromTable)();
socket.write(data);
};
// 模拟从客户端读取消息并写入数据库的操作
const writeMessageToDB = async (message) => {
await promisify(writeMessage)(message);
};
// 监听socket的数据接收事件
socket.on('data', async (data) => {
console.log(`Received message: ${data.toString()}`);
await writeMessageToDB(data.toString());
});
// 定时从数据库读取数据发送给客户端
setInterval(() => {
readFromDatabase();
}, 5000); // 每5秒读一次数据库
// 处理客户端断开连接
socket.on('end', () => {
console.log('Client disconnected');
});
});
// 启动服务器
server.listen(3000, () => {
console.log('Server listening on port 3000');
});
// 示例函数:模拟从数据库读取数据
function readDataFromTable() {
return new Promise(resolve => {
setTimeout(() => {
resolve('Data from database');
}, 1000);
});
}
// 示例函数:模拟将消息写入数据库
function writeMessage(message) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`Message written to DB: ${message}`);
resolve();
}, 1000);
});
}
解释
- 服务器创建:使用
net.createServer()
创建一个TCP服务器,并传入一个回调函数,当有新连接时调用该函数。 - 数据读取与写入:为
socket
对象添加data
事件监听器,当接收到客户端数据时触发。在此示例中,我们将数据作为字符串处理,并将其传递给writeMessageToDB
函数以模拟写入数据库的操作。 - 定时任务:使用
setInterval
每5秒调用一次readFromDatabase
函数,模拟从数据库读取数据并发送给客户端的过程。 - 错误处理:为
socket
添加error
事件监听器,以便在发生错误时捕获它们。 - 断开连接:添加
end
事件监听器来处理客户端断开连接的情况。
以上代码展示了如何在Node.js中同时处理读写socket,同时执行数据库读写操作。注意,这里的数据库读写是模拟的,你需要根据实际情况替换为实际的数据库操作。