当前位置: 首页 > 知识库问答 >
问题:

如何计算Node.js套接字缓冲区以避免分配内存而从不使用它?

丰佐
2023-03-14

我使用Node.js作为两个客户端之间的服务器来处理我的在线游戏。客户端在hem之间发送短消息[一条消息不能超过200字节]。目前,我期望单个客户机[平均]每秒发送1条消息[请记住,这可能是5秒内什么都没有,一个接一个地发送5条消息]。

我已经使用'NET'模块下载了一个示例服务器,并重写了它,以按照我需要的方式处理消息。基本上,对于每个连接的套接字,它创建一个大小为1024*8的缓冲区。目前我正在用一些机器人测试我的游戏,它们只需连接,等待3秒钟就可以断开连接。他们只发送1条信息。没有别的事情发生。

function sendMessage(socket, message) {
    socket.write(message);
}

server.on('connection', function(socket) {
    socket.setNoDelay(true);
    socket.connection_id = require('crypto').createHash('sha1').update( 'krystian'  + Date.now() + Math.random() ).digest('hex') ; // unique sha1 hash generation
    socket.channel = '';
    socket.matchInProgress = false
    socket.resultAnnounced = false;
    socket.buffer = new Buffer(cfg.buffer_size);
    socket.buffer.len = 0; // due to Buffer's nature we have to keep track of buffer contents ourself

    _log('New client: ' + socket.remoteAddress +':'+ socket.remotePort);

    socket.on('data', function(data_raw) { // data_raw is an instance of Buffer as well
        if (data_raw.length > (cfg.buffer_size - socket.buffer.len)) {
            _log("Message doesn't fit the buffer. Adjust the buffer size in configuration");
            socket.buffer.len = 0; // trimming buffer
            return false;
        }

        socket.buffer.len +=  data_raw.copy(socket.buffer, socket.buffer.len); // keeping track of how much data we have in buffer

        var str, start, end
            , conn_id = socket.connection_id;
        str = socket.buffer.slice(0,socket.buffer.len).toString();

        if ( (start = str.indexOf("<somthing>")) !=  -1   &&   (end = str.indexOf("</something>"))  !=  -1) {
            try {
                if (!<some check to see if the message format is right>) {
                        sendMessage(socket, "<error message to the client>");
                    return;
                }
                <storing info on the socket>

            } catch(err) {
                sendMessage(socket, "<error message to the client>");
                return;
            }
            socket.channel = <channel>;
            str = str.substr(end + 11);
            socket.buffer.len = socket.buffer.write(str, 0);
            sockets[socket.channel] = sockets[socket.channel] || {}; // hashmap of sockets  subscribed to the same channel
            sockets[socket.channel][conn_id] = socket;
            waiting[socket.channel] = waiting[socket.channel] || {};
            waiting[socket.channel][conn_id] = socket;
            sendMessage(socket, "<info message to the client>");
            for (var prop in waiting[socket.channel]) {
                if (waiting[socket.channel].hasOwnProperty(prop) && waiting[socket.channel][prop].connection_id != socket.connection_id) {
                   <here I'll try to advertise this client among other clients>
                    sendMessage(waiting[socket.channel][prop], "<info to other clients about new client>");
                }
            }
        }

        var time_to_exit = true;
        do{  // this is for a case when several messages arrived in buffer
            if ( (start = str.indexOf("<some other format>")) !=  -1   &&  (end = str.indexOf("</some other format>"))  !=  -1 ) {
                var json = str.substr( start+19,  end-(start+19) );
                var jsono;
                try {
                    jsono = JSON.parse(json);
                } catch(err) {
                    sendMessage(socket, "<parse error>");
                    return;
                }
                if (<message indicates two clients are going to play together>) {
                    if (waiting[socket.channel][jsono.other_client_id] && waiting[socket.channel][socket.connection_id]) {
                        delete waiting[socket.channel][jsono.other_client_id];
                        delete waiting[socket.channel][socket.connection_id];
                        var opponentSocket = sockets[socket.channel][jsono.other_client_id];
                        sendMessage(opponentSocket, "<start game with the other socket>");
                        opponentSocket.opponentConnectionId = socket.connection_id;
                        sendMessage(socket, "<start game with the other socket>");
                        socket.opponentConnectionId = jsono.other_client_id;
                    }
                } else if (<check if clients play together>) { 
                    var opponentSocket = sockets[socket.channel][socket.opponentConnectionId];
                    if (<some generic action between clients, just pass the message>) {
                        sendMessage(sockets[socket.channel][socket.opponentConnectionId], json);
                    } else if (<match is over>) {
                        if (<match still in progress>) {
                            <send some messages indicating who won, who lost>
                        } else {
                            <log an error>
                        }
                        delete sockets[socket.channel][opponentSocket.connection_id];
                        delete sockets[socket.channel][socket.connection_id];
                    }
                }
                str = str.substr(end + 20);  // cut the message and remove the precedant part of the buffer since it can't be processed
                socket.buffer.len = socket.buffer.write(str, 0);
                time_to_exit = false;
            } else {  time_to_exit = true; } // if no json data found in buffer - then it is time to exit this loop
        } while ( !time_to_exit );
    }); // end of  socket.on 'data'


    socket.on('close', function(){  // we need to cut out closed socket from array of client socket connections
        if  (!socket.channel   ||   !sockets[socket.channel])  return;
        if (waiting[socket.channel] && waiting[socket.channel][socket.connection_id]) {
            delete waiting[socket.channel][socket.connection_id];
        }

        var opponentSocket = sockets[socket.channel][socket.opponentConnectionId];
        if (opponentSocket) {
            sendMessage(opponentSocket, "<the other client has disconnected>");
            delete sockets[socket.channel][socket.opponentConnectionId];
        }

        delete sockets[socket.channel][socket.connection_id];
        _log(socket.connection_id + " has been disconnected from channel " + socket.channel);
    }); // end of socket.on 'close'

}); //  end of server.on 'connection'

server.on('listening', function(){ console.log('Listening on ' + server.address().address +':'+ server.address().port); });
server.listen(cfg.port);
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                                                                                
31461 ec2-user  20   0  995m  91m 7188 S  0.7 15.4   1:29.07 node           

我只是想知道,我关于缓冲区大小的假设是否正确。我是否应该调整缓冲区以反映我期望从客户端获得的数据量?如果我期望客户机发送5条消息,每条消息之间的时间非常短,最多200字节,我应该假设1024*3就足够了吗?

或者我应该根据我期望的消息大小来调整缓冲区大小,这样如果我确定消息永远不会超过300字节,那么缓冲区大小应该为512就可以了?

谢谢,克里斯蒂安

$ node -v
v0.10.5
$ npm -v
1.2.19

共有1个答案

喻选
2023-03-14

内核有一个至少8K的套接字接收缓冲区,用于处理套接字上的多个传入消息。您不需要缓冲已经读取的消息,因此应用程序缓冲区不需要大于预期的最大消息。

 类似资料:
  • 我正在尝试正确地使用ByteBuffer和BigEndian字节顺序格式。。 我有几个字段,我试图把它存储在Cassandra数据库之前放在一个单一的ByteBuffer中。 我将要写入Cassandra的字节数组由三个字节数组组成,如下所述- 现在,我需要快速压缩attributeValue数据,然后再将其存储在Cassandra中- 现在,我将编写,和snappy压缩的一起组成一个单字节数组,

  • 我正在尝试为DMA Linux编写驱动程序,但我的驱动程序一直无法执行DMA_CONCENTER_alloc,我已经增加了CMA内存和CONCENTERY_pool。。。 我错过了什么? dmesg在物理CPU 0x0上引导Linux<br>Linux版本4.14.0-xilinx-v2018.2(oe-user@oe-host)(gcc版本7.2.0(gcc))#5 SMP抢占Sun二月17日2

  • 问题内容: 假设我想使用标准模块从套接字读取一行: 到底发生了什么?每次都会发出系统调用吗?我想无论如何我应该添加一些缓冲: 为了与硬件和网络实际情况达到最佳匹配, bufsize 的值应为2的相对较小的幂,例如4096。 http://docs.python.org/library/socket.html#socket.socket.recv 但是编写高效且线程安全的缓冲似乎并不容易。如果我使用

  • 问题内容: Linux的默认套接字缓冲区大小是多少?有什么命令可以看到吗? 问题答案: 如果要在终端中查看缓冲区大小,可以看一下: (供阅读) (写) 它们包含三个数字,分别是最小,默认和最大内存大小值(以字节为单位)。

  • 问题内容: 我有一个带有两列的pandas数据框:x和value。我想查找x == 10的所有行,并为所有这些行设置值= 1,000。我尝试了下面的代码,但收到警告 我知道我可以通过使用.loc或.ix来避免这种情况,但是我首先需要找到满足x == 10的条件的所有行的位置或索引。有没有更直接的方法? 谢谢! 问题答案: 您应该使用以确保您正在使用视图,在您的示例中以下内容将起作用并且不会发出警告

  • 问题内容: 在编写用于OpenGL库的Matrix类时,我遇到了一个问题,即使用Java数组还是使用Buffer策略存储数据(JOGL为Matrix操作提供直接缓冲区复制)。为了对此进行分析,我编写了一个小型性能测试程序,该程序比较了Arrays vs Buffers和Direct Buffers上循环和批量操作的相对速度。 我想在这里与您分享我的结果(因为我发现它们很有趣)。请随时发表评论和/或