Nodejs: Set highWaterMark of socket object
是否可以在创建套接字对象后设置它的highWaterMark:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | var http = require('http'); var server = http.createServer(); server.on('upgrade', function(req, socket, head) { socket.on('data', function(chunk) { var frame = new WebSocketFrame(chunk); // skip invalid frames if (!frame.isValid()) return; // if the length in the head is unequal to the chunk // node has maybe split it if (chunk.length != WebSocketFrame.getLength()) { socket.once('data', listenOnMissingChunks); }); }); }); function listenOnMissingChunks(chunk, frame) { frame.addChunkToPayload(chunk); if (WebSocketFrame.getLength()) { // if still corrupted listen once more } else { // else proceed } } |
上面的代码示例不起作用。但是我该怎么做呢?
进一步的解释:
当我收到大的WebSocket框架时,它们会分成多个数据事件。这使解析帧变得很困难,因为我不知道这是分裂还是损坏的帧。
我认为您误解了TCP套接字的性质。尽管TCP通过IP数据包发送数据,但TCP并不是数据包协议。 TCP套接字只是数据流。因此,将
许多原因导致对套接字的单次写入未将1:1映射到单个
- 发送者的网络堆栈可以将多个小写操作合并到一个IP数据包中。 (Nagle算法)
- 如果IP数据包的大小超过任何一跳的MTU,则可能沿其行程分段(拆分为多个数据包)。
-
接收者的网络堆栈可能会将多个数据包组合成一个
data 事件(如您的应用程序所见)。
因此,单个
为了正确处理通过流发送的消息,必须缓冲传入的数据,直到获得完整的消息为止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | var net = require('net'); var max = 1024 * 1024 // 1 MB, the maximum amount of data that we will buffer (prevent a bad server from crashing us by filling up RAM) , allocate = 4096; // how much memory to allocate at once, 4 kB (there's no point in wasting 1 MB of RAM to buffer a few bytes) , buffer=new Buffer(allocate) // create a new buffer that allocates 4 kB to start , nread=0 // how many bytes we've buffered so far , nproc=0 // how many bytes in the buffer we've processed (to avoid looping over the entire buffer every time data is received) , client = net.connect({host:'example.com', port: 8124}); // connect to the server client.on('data', function(chunk) { if (nread + chunk.length > buffer.length) { // if the buffer is too small to hold the data var need = Math.min(chunk.length, allocate); // allocate at least 4kB if (nread + need > max) throw new Error('Buffer overflow'); // uh-oh, we're all full - TODO you'll want to handle this more gracefully var newbuf = new Buffer(buffer.length + need); // because Buffers can't be resized, we must allocate a new one buffer.copy(newbuf); // and copy the old one's data to the new one buffer = newbuf; // the old, small buffer will be garbage collected } chunk.copy(buffer, nread); // copy the received chunk of data into the buffer nread += chunk.length; // add this chunk's length to the total number of bytes buffered pump(); // look at the buffer to see if we've received enough data to act }); client.on('end', function() { // handle disconnect }); client.on('error', function(err) { // handle errors }); function find(byte) { // look for a specific byte in the buffer for (var i = nproc; i < nread; i++) { // look through the buffer, starting from where we left off last time if (buffer.readUInt8(i, true) == byte) { // we've found one return i; } } } function slice(bytes) { // discard bytes from the beginning of a buffer buffer = buffer.slice(bytes); // slice off the bytes nread -= bytes; // note that we've removed bytes nproc = 0; // and reset the processed bytes counter } function pump() { var pos; // position of a NULL character while ((pos = find(0x00)) >= 0) { // keep going while there's a NULL (0x00) somewhere in the buffer if (pos == 0) { // if there's more than one NULL in a row, the buffer will now start with a NULL slice(1); // discard it continue; // so that the next iteration will start with data } process(buffer.slice(0,pos)); // hand off the message slice(pos+1); // and slice the processed data off the buffer } } function process(msg) { // here's where we do something with a message if (msg.length > 0) { // ignore empty messages // here's where you have to decide what to do with the data you've received // experiment with the protocol } } |
您不需要。几乎可以肯定,传入的数据将分为两次或多次读取:这是TCP的本质,您无能为力。摆弄晦涩的套接字参数当然不会改变它。数据将点亮,但肯定不会损坏。只需将套接字视作是什么:字节流。