3

我无法从本机 C++ WebSocket (www.websocket.org) 客户端与 socket.io 服务器交换数据。请注意,我不想要基于 Boost 的解决方案,因为我正在从嵌入式系统运行 WebSocket 客户端(它必须是轻量级的)。

我已经尝试过 LWS_WRITE_TEXT 和 LWS_WRITE_HTTP(无填充)模式。我没有使用安全套接字(即,不使用 wss 或 SSL 证书)。

myServer.js:

var io = require('socket.io').listen(80);

io.configure('production', function(){
  io.enable('browser client etag');
  io.set('log level', 3);
  io.set('transports', ['websocket']);
});

io.configure('development', function(){
  io.set('log level', 3);
  io.set('transports', ['websocket']);
});

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

我已经增强了 libwebsockets-test-echo.cpp 示例代码作为起点,并且当客户端和服务器都使用 WebSockets C++ API 时它可以正常工作。但是,当我连接到 socket.io 服务器时,服务器控制台会报告: warn - unknown transport: "undefined" 。

客户端.cpp:

...
    struct per_session_data__echo {
    // for LWS_WRITE_TEXT mode, PRE_PADDING is defined to LWS_SEND_BUFFER_PRE_PADDING and POST_PADDING is LWS_SEND_BUFFER_POST_PADDING, otherwise they're both set to 0.
    unsigned char buf[PRE_PADDING + 1400 + POST_PADDING];
    unsigned int len;
    unsigned int index;
};

static int callback_echo(struct libwebsocket_context *context,
    struct libwebsocket *wsi,
    enum libwebsocket_callback_reasons reason, void *user,
    void *in, size_t len)
{
    struct per_session_data__echo *pss = (struct per_session_data__echo *)user;
    int n;

    switch (reason) {
    case LWS_CALLBACK_CLIENT_ESTABLISHED:
        lwsl_notice("Client has connected\n");
        pss->index = 0;
        break;

    case LWS_CALLBACK_CLIENT_RECEIVE:
        lwsl_notice("Client RX: %s", (char *)in);
        break;

    case LWS_CALLBACK_CLIENT_WRITEABLE:
        /* we will send our packet... */
        pss->len = sprintf((char *)&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], "hello from libwebsockets-test-echo client pid %d index %d\n", getpid(), pss->index++);
        lwsl_notice("Client TX: %s", &pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);
        n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
        if (n < 0) {
            lwsl_err("ERROR %d writing to socket, hanging up\n", n);
            return -1;
        }
        if (n < (int)pss->len) {
            lwsl_err("Partial write\n");
            return -1;
        }
        break;
    default:
        break;
    }

    return 0;
}

static struct libwebsocket_protocols protocols[] = {
    /* first protocol must always be HTTP handler */
    {
        "my other event",      /* name */
        callback_echo,      /* callback */
        sizeof(struct per_session_data__echo),  /* per_session_data_size */
        0
    },
    {
        NULL, NULL, 0, 0       /* End of list */
    }
};

...

struct lws_context_creation_info info;
info.port = CONTEXT_PORT_NO_LISTEN;
info.iface = "eth0";
info.gid = -1;
info.uid = -1;
info.options = 0;
info.extensions = libwebsocket_get_internal_extensions();
info.protocols = protocols;

libwebsocket_context context_;
context_ = libwebsocket_create_context(&info);

libwebsocket *wsi_;
wsi_ = libwebsocket_client_connect(context_,
    "localhost",
    80, // port
    0, // "ws:" (no SSL)
    "/socket.io", // path
    "localhost", // host name
    "controller", // Socket origin name
    "my other event", // libwebsocket protocol name
    -1
    );

...
libwebsocket_callback_on_writable_all_protocol(&protocols_[0]);

...
int rc = 0;
unsigned int oldus = 0;
while (rc >= 0 && !forceExit_) {
    struct timeval tv;

    gettimeofday(&tv, NULL);

    if (((unsigned int)tv.tv_usec - oldus) > pollingRate_) {
        oldus = tv.tv_usec;
    }
    rc = libwebsocket_service(context_, 1000); // wait 1000 msec
    if (rc != 0) printf("rc=%d\n", rc);
}

...

这是“sudo node server.js”的输出:

  info  - socket.io started
  warn  - unknown transport: "undefined"

这是 client.cpp 控制台的输出。不要被“listening on port=0”误导,因为它是 libwebsockets-test-echo.cpp 使用的上下文端口设置,它适用于 websocket 到 websocket 客户端和服务器。请注意,连接完成,对于 LWS_WRITE_TEXT 和 LWS_WRITE_HTTP 模式,此输出相同。

listening on port=0
listening on interface=eth0
lwsts[12960]: Initial logging level 7
lwsts[12960]: Library version: 1.3 502b994
lwsts[12960]:  Started with daemon pid 0
lwsts[12960]:  static allocation: 4488 + (16 x 1024 fds) = 20872 bytes
lwsts[12960]:  canonical_hostname = sogo
lwsts[12960]: context->protocols[0].name='my other event'
lwsts[12960]: LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS
lwsts[12960]: context->protocols[0].name='my other event'
lwsts[12960]: LWS_CALLBACK_PROTOCOL_INIT
lwsts[12960]: WebSocketClient::connect(): connecting to localhost:80 ...
sslCerts=0
protocolNameList='my other event'
connecting to address=localhost and port=80
lwsts[13340]: context->protocols[0].name='my other event'
lwsts[13340]: LWS_CALLBACK_ADD_POLL_FD
lwsts[13340]: context->protocols[0].name='my other event'
lwsts[13340]: LWS_CALLBACK_CLEAR_MODE_POLL_FD
lwsts[13340]: context->protocols[0].name='my other event'
lwsts[13340]: LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED
lwsts[13340]: context->protocols[0].name='my other event'
lwsts[13340]: LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER
lwsts[13340]: WebSocketClient::connect(): connected to localhost:80
lwsts[13340]: context->protocols[0].name='my other event'
lwsts[13340]: LWS_CALLBACK_SET_MODE_POLL_FD
lwsts[13340]: WebSocketClient::run(): running ...
lwsts[13340]: problems parsing header
lwsts[13340]: context->protocols[0].name='my other event'
lwsts[13340]: LWS_CALLBACK_DEL_POLL_FD
4

0 回答 0