libwebsocket:无法写入大于 7160 字节的帧

libwebsocket: unable to write frame bigger than 7160 bytes

我正在解决一个我无法理解的 WebSocket 问题。
请使用以下代码作为参考:

int write_buffer_size = 8000 +
                LWS_SEND_BUFFER_PRE_PADDING +
                LWS_SEND_BUFFER_POST_PADDING;

char *write_buffer = new unsigned char[write_buffer_size];

/* ... other code
   write_buffer is filled in some way that is not important for the question
*/

n = libwebsocket_write(wsi, &write_buffer[LWS_SEND_BUFFER_PRE_PADDING], write_len,
            (libwebsocket_write_protocol)write_mode);
    if (n < 0) {
        cerr << "ERROR " << n << " writing to socket, hanging up" << endl;
        if (utils) {
            log = "wsmanager::error: hanging up writing to websocket";
            utils->writeLog(log);
        }
        return -1;
    }
    if (n < write_len) {
        cerr << "Partial write: " << n << " < " << write_len << endl;
        if (utils) {
            log = "wsmanager-error: websocket partial write";
            utils->writeLog(log);
        }
        return -1;
    }

当我尝试发送大于 7160 字节的数据时,我总是收到相同的错误,例如部分写入:7160 < 8000
你对这种行为有什么解释吗?
我已经为有效负载分配了一个保留了 8000 字节的缓冲区,所以我希望能够发送最大 8K 的数据量,但 7160(字节)似乎是我可以发送的最大数据量。
感谢任何帮助,谢谢!

我在旧版本的 libwebsockets 上遇到过类似的问题。虽然我没有监控限制,但它几乎是同一件事:n < write_len。我认为我的限制要低得多,低于 2048B,而且我知道相同的代码在较新版本的 libwebsockets 上运行良好(在不同的机器上)。

由于 Debian Jessie 在存储库中没有 lws v1.6,我从 github sources. Consider upgrading, it may help solve your problem. Beware, they have changed api. It was mostly renaming of methods' names from libwebsocket_* to lws_*, but also some arguments changed. Check this pull request 构建了它,它将 boilerplate libwebsockets server 迁移到版本 1.6。这些更改中的大部分都会影响您的代码。

我们解决了将 libwebsockets 更新到 1.7.3 版本的问题。
我们还使用通道可写时调用的自定义回调优化了代码

void
WSManager::onWritable() {
    int ret, n;
    struct fragment *frg;

    pthread_mutex_lock(&send_queue_mutex);

    if (!send_queue.empty() && !lws_partial_buffered(wsi)) {
        frg = send_queue.front();

        n = lws_write(wsi, frg->content + LWS_PRE, frg->len, (lws_write_protocol)frg->mode);
        ret = checkWsWrite(n, frg->len);

        if (ret >= 0 && !lws_partial_buffered(wsi)) {
            if (frg->mode == WS_SINGLE_FRAGMENT || frg->mode == WS_LAST_FRAGMENT)
                signalResponseSent();

            // pop fragment and free memory only if lws_write was successful
            send_queue.pop();
            delete(frg);
        }
    }
    pthread_mutex_unlock(&send_queue_mutex);
}