如何将 libwebsockets C 客户端连接到 wsrelay 服务器 (node.js)
How to connect a libwebsockets C client to a wsrelay server (node.js)
在我的 mac 上,我安装了 运行 wsrelay
$ wsrelay
listening on port 8124...
在我的 Ubuntu 14.04 上,我编译并 运行 一个简单的 libwebsockets
客户端连接到 wsrelay
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <libwebsockets.h>
#define KGRN "3[0;32;32m"
#define KCYN "3[0;36m"
#define KRED "3[0;32;31m"
#define KYEL "3[1;33m"
#define KBLU "3[0;32;34m"
#define KCYN_L "3[1;36m"
#define KBRN "3[0;33m"
#define RESET "3[0m"
static int destroy_flag = 0;
static int connection_flag = 0;
static int writeable_flag = 0;
static void INT_HANDLER(int signo) {
destroy_flag = 1;
}
struct session_data {
int fd;
};
static int websocket_write_back(struct lws *wsi_in, char *str, int str_size_in)
{
if (str == NULL || wsi_in == NULL)
return -1;
int n;
int len;
char *out = NULL;
if (str_size_in < 1)
len = strlen(str);
else
len = str_size_in;
out = (char *)malloc(sizeof(char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING));
//* setup the buffer*/
memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, str, len );
//* write out*/
n = lws_write(wsi_in, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT);
printf(KBLU"[websocket_write_back] %s\n"RESET, str);
//* free the buffer*/
free(out);
return n;
}
static int ws_service_callback(
struct lws *wsi,
enum lws_callback_reasons reason, void *user,
void *in, size_t len)
{
switch (reason) {
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf(KYEL"[Main Service] Connect with server success.\n"RESET);
connection_flag = 1;
websocket_write_back(wsi, "CLT - Client connected to server!", -1);
break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf(KRED"[Main Service] Connect with server error.\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;
case LWS_CALLBACK_CLOSED:
printf(KYEL"[Main Service] LWS_CALLBACK_CLOSED\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
printf(KCYN_L"[Main Service] Client received:%s\n"RESET, (char *)in);
break;
case LWS_CALLBACK_CLIENT_WRITEABLE :
printf(KYEL"[Main Service] On writeable is called. send byebye message\n"RESET);
websocket_write_back(wsi, "Byebye! See you later", -1);
writeable_flag = 1;
break;
default:
break;
}
return 0;
}
int main(void)
{
//* register the signal SIGINT handler */
struct sigaction act;
act.sa_handler = INT_HANDLER;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction( SIGINT, &act, 0);
struct lws_context *context = NULL;
struct lws_context_creation_info info;
struct lws *wsi = NULL;
struct lws_protocols protocol;
memset(&info, 0, sizeof info);
info.port = CONTEXT_PORT_NO_LISTEN;
info.iface = NULL;
info.protocols = &protocol;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.extensions = lws_get_internal_extensions();
info.gid = -1;
info.uid = -1;
info.options = 0;
protocol.name = "my-echo-protocol";
protocol.callback = &ws_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 0;
protocol.id = 0;
protocol.user = NULL;
context = lws_create_context(&info);
printf(KRED"[Main] context created.\n"RESET);
if (context == NULL) {
printf(KRED"[Main] context is NULL.\n"RESET);
return -1;
}
wsi = lws_client_connect(context, "Mac-IP-address", 8124, 0,
"/", "Mac-IP-address:8124", NULL,
protocol.name, -1);
if (wsi == NULL) {
printf(KRED"[Main] wsi create error.\n"RESET);
return -1;
}
printf(KGRN"[Main] wsi create success.\n"RESET);
while(!destroy_flag)
{
lws_service(context, 50);
}
lws_context_destroy(context);
return 0;
}
但是当我 运行 客户端时,使用 websocket_write_back
发送到服务器的消息从未到达服务器,尽管连接似乎已正确建立。我猜这是关于协议的事情??关于我可能做错了什么的任何指示?
$ ./example-client
[1452543414:0970] NOTICE: Initial logging level 7
[1452543414:0971] NOTICE: Libwebsockets version: 1.6.0 0c7e5a9
[1452543414:0971] NOTICE: IPV6 not compiled in
[1452543414:0971] NOTICE: libev support not compiled in
[1452543414:0972] NOTICE: mem: platform fd map: 8192 bytes
[1452543414:0972] NOTICE: mem: per-conn: 352 bytes + protocol rx buf
[1452543414:0972] NOTICE: canonical_hostname = linux-Lenovo-G50-70
[Main] context created.
[Main] wsi create success.
[Main Service] Connect with server success.
[websocket_write_back] CLT - Client connected to server!
不确定您在此期间是否设法解决了它。这是我的猜测:您的代码很好,wsrelay.
有问题
我已经 运行 你的代码(gcc 抱怨一些打字,我会在这个答案的底部附加差异)并且一切似乎都工作正常。但是 wsrelay 没有像你说的那样报告任何东西,这是可疑的,所以我创建了不同的 ws 服务器。基本上相同的功能(我想,从来没有真正看到 wsrelay 工作......) - 它记录客户端连接,打印发送的消息并记录客户端断开连接。
此服务器能够捕获您的消息。所以我鼓励你删除 wsrelay 并使用下面的服务器代码作为你的基础。它是我找到的代码的精简版 here。希望这有帮助。
WS 服务器源
var webSocketsServerPort = 8124;
var webSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {});
server.listen(webSocketsServerPort, function() {
console.log((new Date()) + " Server is listening on port " + webSocketsServerPort);
});
var wsServer = new webSocketServer({httpServer: server});
wsServer.on('request', function(request) {
console.log((new Date()), 'New connection.');
var connection = request.accept();
connection.on('message', function(message) {
console.log(message.utf8Data);
});
connection.on('close', function(connection) {
console.log((new Date()), 'Connection closed.');
});
});
WS 服务器输出
$ node server.js
Sun Feb 14 2016 13:57:43 GMT+0100 (CET) Server is listening on port 8124
Sun Feb 14 2016 13:57:44 GMT+0100 (CET) 'New connection.'
CLT - Client connected to server!
Byebye! See you later
Byebye! See you later
Sun Feb 14 2016 13:58:31 GMT+0100 (CET) 'Connection closed.'
您的 C 客户端输出(来自 gdb)
$ gdb stack
...
(gdb) run
Starting program: /tmp/stack
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[1455454664:6989] NOTICE: Initial logging level 7
[1455454664:6989] NOTICE: Libwebsockets version: 1.6.0 unknown-build-hash
[1455454664:6989] NOTICE: IPV6 not compiled in
[1455454664:6989] NOTICE: libev support not compiled in
[1455454664:6989] NOTICE: ctx mem: 21088 bytes
[1455454664:6990] NOTICE: canonical_hostname = gentee
[1455454664:6990] NOTICE: per-conn mem: 256 + 2126 headers + protocol rx buf
[Main] context created.
[Main] wsi create success.
[Main Service] Connect with server success.
[websocket_write_back] CLT - Client connected to server!
[Main Service] On writeable is called. send byebye message
[websocket_write_back] Byebye! See you later
[Main Service] On writeable is called. send byebye message
[websocket_write_back] Byebye! See you later
^C
差异(为了 运行 你的客户我必须做的修改)
$ diff --unchanged-line-format="" --old-line-format="" --new-line-format="%dn: %L" /tmp/stack.*
36: unsigned char *out = NULL;
43: out = (unsigned char *)malloc(sizeof(unsigned char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING));
68: websocket_write_back(wsi, (char *)"CLT - Client connected to server!", -1);
89: websocket_write_back(wsi, (char *)"Byebye! See you later", -1);
141: wsi = lws_client_connect(context, "localhost", 8124, 0,
142: "/", "localhost:8124", NULL,
在我的 mac 上,我安装了 运行 wsrelay
$ wsrelay
listening on port 8124...
在我的 Ubuntu 14.04 上,我编译并 运行 一个简单的 libwebsockets
客户端连接到 wsrelay
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <libwebsockets.h>
#define KGRN "3[0;32;32m"
#define KCYN "3[0;36m"
#define KRED "3[0;32;31m"
#define KYEL "3[1;33m"
#define KBLU "3[0;32;34m"
#define KCYN_L "3[1;36m"
#define KBRN "3[0;33m"
#define RESET "3[0m"
static int destroy_flag = 0;
static int connection_flag = 0;
static int writeable_flag = 0;
static void INT_HANDLER(int signo) {
destroy_flag = 1;
}
struct session_data {
int fd;
};
static int websocket_write_back(struct lws *wsi_in, char *str, int str_size_in)
{
if (str == NULL || wsi_in == NULL)
return -1;
int n;
int len;
char *out = NULL;
if (str_size_in < 1)
len = strlen(str);
else
len = str_size_in;
out = (char *)malloc(sizeof(char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING));
//* setup the buffer*/
memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, str, len );
//* write out*/
n = lws_write(wsi_in, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT);
printf(KBLU"[websocket_write_back] %s\n"RESET, str);
//* free the buffer*/
free(out);
return n;
}
static int ws_service_callback(
struct lws *wsi,
enum lws_callback_reasons reason, void *user,
void *in, size_t len)
{
switch (reason) {
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf(KYEL"[Main Service] Connect with server success.\n"RESET);
connection_flag = 1;
websocket_write_back(wsi, "CLT - Client connected to server!", -1);
break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf(KRED"[Main Service] Connect with server error.\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;
case LWS_CALLBACK_CLOSED:
printf(KYEL"[Main Service] LWS_CALLBACK_CLOSED\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
printf(KCYN_L"[Main Service] Client received:%s\n"RESET, (char *)in);
break;
case LWS_CALLBACK_CLIENT_WRITEABLE :
printf(KYEL"[Main Service] On writeable is called. send byebye message\n"RESET);
websocket_write_back(wsi, "Byebye! See you later", -1);
writeable_flag = 1;
break;
default:
break;
}
return 0;
}
int main(void)
{
//* register the signal SIGINT handler */
struct sigaction act;
act.sa_handler = INT_HANDLER;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction( SIGINT, &act, 0);
struct lws_context *context = NULL;
struct lws_context_creation_info info;
struct lws *wsi = NULL;
struct lws_protocols protocol;
memset(&info, 0, sizeof info);
info.port = CONTEXT_PORT_NO_LISTEN;
info.iface = NULL;
info.protocols = &protocol;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.extensions = lws_get_internal_extensions();
info.gid = -1;
info.uid = -1;
info.options = 0;
protocol.name = "my-echo-protocol";
protocol.callback = &ws_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 0;
protocol.id = 0;
protocol.user = NULL;
context = lws_create_context(&info);
printf(KRED"[Main] context created.\n"RESET);
if (context == NULL) {
printf(KRED"[Main] context is NULL.\n"RESET);
return -1;
}
wsi = lws_client_connect(context, "Mac-IP-address", 8124, 0,
"/", "Mac-IP-address:8124", NULL,
protocol.name, -1);
if (wsi == NULL) {
printf(KRED"[Main] wsi create error.\n"RESET);
return -1;
}
printf(KGRN"[Main] wsi create success.\n"RESET);
while(!destroy_flag)
{
lws_service(context, 50);
}
lws_context_destroy(context);
return 0;
}
但是当我 运行 客户端时,使用 websocket_write_back
发送到服务器的消息从未到达服务器,尽管连接似乎已正确建立。我猜这是关于协议的事情??关于我可能做错了什么的任何指示?
$ ./example-client
[1452543414:0970] NOTICE: Initial logging level 7
[1452543414:0971] NOTICE: Libwebsockets version: 1.6.0 0c7e5a9
[1452543414:0971] NOTICE: IPV6 not compiled in
[1452543414:0971] NOTICE: libev support not compiled in
[1452543414:0972] NOTICE: mem: platform fd map: 8192 bytes
[1452543414:0972] NOTICE: mem: per-conn: 352 bytes + protocol rx buf
[1452543414:0972] NOTICE: canonical_hostname = linux-Lenovo-G50-70
[Main] context created.
[Main] wsi create success.
[Main Service] Connect with server success.
[websocket_write_back] CLT - Client connected to server!
不确定您在此期间是否设法解决了它。这是我的猜测:您的代码很好,wsrelay.
有问题我已经 运行 你的代码(gcc 抱怨一些打字,我会在这个答案的底部附加差异)并且一切似乎都工作正常。但是 wsrelay 没有像你说的那样报告任何东西,这是可疑的,所以我创建了不同的 ws 服务器。基本上相同的功能(我想,从来没有真正看到 wsrelay 工作......) - 它记录客户端连接,打印发送的消息并记录客户端断开连接。
此服务器能够捕获您的消息。所以我鼓励你删除 wsrelay 并使用下面的服务器代码作为你的基础。它是我找到的代码的精简版 here。希望这有帮助。
WS 服务器源
var webSocketsServerPort = 8124;
var webSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {});
server.listen(webSocketsServerPort, function() {
console.log((new Date()) + " Server is listening on port " + webSocketsServerPort);
});
var wsServer = new webSocketServer({httpServer: server});
wsServer.on('request', function(request) {
console.log((new Date()), 'New connection.');
var connection = request.accept();
connection.on('message', function(message) {
console.log(message.utf8Data);
});
connection.on('close', function(connection) {
console.log((new Date()), 'Connection closed.');
});
});
WS 服务器输出
$ node server.js
Sun Feb 14 2016 13:57:43 GMT+0100 (CET) Server is listening on port 8124
Sun Feb 14 2016 13:57:44 GMT+0100 (CET) 'New connection.'
CLT - Client connected to server!
Byebye! See you later
Byebye! See you later
Sun Feb 14 2016 13:58:31 GMT+0100 (CET) 'Connection closed.'
您的 C 客户端输出(来自 gdb)
$ gdb stack
...
(gdb) run
Starting program: /tmp/stack
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[1455454664:6989] NOTICE: Initial logging level 7
[1455454664:6989] NOTICE: Libwebsockets version: 1.6.0 unknown-build-hash
[1455454664:6989] NOTICE: IPV6 not compiled in
[1455454664:6989] NOTICE: libev support not compiled in
[1455454664:6989] NOTICE: ctx mem: 21088 bytes
[1455454664:6990] NOTICE: canonical_hostname = gentee
[1455454664:6990] NOTICE: per-conn mem: 256 + 2126 headers + protocol rx buf
[Main] context created.
[Main] wsi create success.
[Main Service] Connect with server success.
[websocket_write_back] CLT - Client connected to server!
[Main Service] On writeable is called. send byebye message
[websocket_write_back] Byebye! See you later
[Main Service] On writeable is called. send byebye message
[websocket_write_back] Byebye! See you later
^C
差异(为了 运行 你的客户我必须做的修改)
$ diff --unchanged-line-format="" --old-line-format="" --new-line-format="%dn: %L" /tmp/stack.*
36: unsigned char *out = NULL;
43: out = (unsigned char *)malloc(sizeof(unsigned char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING));
68: websocket_write_back(wsi, (char *)"CLT - Client connected to server!", -1);
89: websocket_write_back(wsi, (char *)"Byebye! See you later", -1);
141: wsi = lws_client_connect(context, "localhost", 8124, 0,
142: "/", "localhost:8124", NULL,