你正试图把水推上山。
警告:我只编写了执行此操作的服务器,而不是客户端;但是,界面非常相似
首先,libwebsockets
是根据您将使用poll
orppoll
而不是select
. 我确信它是可以使用的,但是如果你使用or select
,你的生活会轻松很多;重写我的代码使用大约需要 10 分钟。如果你真的要使用,我建议你让外部轮询工作使用,然后重写使用。poll
ppoll
select()
ppoll
select
ppoll
select()
接下来,看一下,特别是如果定义test-server.c
了代码是如何变化的。EXTERNAL_POLL
您还想阅读以下 API 文档:
接下来的四个原因是可选的,仅当您将 libwebsockets 套接字集成到外部轮询数组时才需要注意。
LWS_CALLBACK_ADD_POLL_FD
libwebsocket 在内部处理其轮询循环,但如果您与另一台服务器集成,则需要让 libwebsocket 套接字与另一台服务器共享一个轮询数组。这个和其他与 POLL_FD 相关的回调让您可以将专用轮询数组接口代码放在协议 0 的回调中,协议 0 是您支持的第一个协议,通常是服务案例中的 HTTP 协议。当需要将套接字添加到包含 fd 的轮询循环中时,会发生此回调,并且 len 是事件位图(如 POLLIN)。如果您使用的是内部轮询循环(“服务”回调),则可以忽略这些回调。
LWS_CALLBACK_DEL_POLL_FD
当需要从外部轮询数组中删除套接字描述符时,会发生此回调。in 是套接字描述符。如果您使用的是内部轮询循环,则可以忽略它。
LWS_CALLBACK_SET_MODE_POLL_FD
当 libwebsockets 想要修改 in 中的套接字描述符的事件时,会发生此回调。处理程序应该或 len 到 pollfd 结构的事件成员上,以获取此套接字描述符。如果您使用的是内部轮询循环,则可以忽略它。
LWS_CALLBACK_CLEAR_MODE_POLL_FD
当 libwebsockets 想要修改 in 中的套接字描述符的事件时,会发生此回调。处理程序应该 AND ~len 到此套接字描述符的 pollfd 结构的 events 成员。如果您使用的是内部轮询循环,则可以忽略它。
这就是说(简单地说)是 libwebsockets 会用这些方法调用你并要求你操作你的poll
数组。
忽略一些关于锁定的复杂性,你可以看到test-server.c
它们是这样实现的:
case LWS_CALLBACK_ADD_POLL_FD:
if (count_pollfds >= max_poll_elements) {
lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
return 1;
}
fd_lookup[pa->fd] = count_pollfds;
pollfds[count_pollfds].fd = pa->fd;
pollfds[count_pollfds].events = pa->events;
pollfds[count_pollfds++].revents = 0;
break;
case LWS_CALLBACK_DEL_POLL_FD:
if (!--count_pollfds)
break;
m = fd_lookup[pa->fd];
/* have the last guy take up the vacant slot */
pollfds[m] = pollfds[count_pollfds];
fd_lookup[pollfds[count_pollfds].fd] = m;
break;
我不相信(服务器端)你需要实现后两个回调,test-server.c
不需要,我不需要。
调用后poll
,您需要请求libwebsockets
服务其自己的 FD,如下所示(再次来自test-server.c
):
/*
* this represents an existing server's single poll action
* which also includes libwebsocket sockets
*/
n = poll(pollfds, count_pollfds, 50);
if (n < 0)
continue;
if (n)
for (n = 0; n < count_pollfds; n++)
if (pollfds[n].revents)
/*
* returns immediately if the fd does not
* match anything under libwebsockets
* control
*/
if (libwebsocket_service_fd(context,
&pollfds[n]) < 0)
goto done;
那么,让我们回到您的具体问题:
所以我尝试了以下步骤。
通过连接 websocketstruct libwebsocket *wsi = libwebsocket_client_connect(..)
我还检查了返回值是否为 NULL 或不是错误。
通过获取文件描述符int fd = libwebsocket_get_socket_fd(wsi);
FD_SET(fd, &readFd);
和select(maxFd + 1, &readFd, NULL, NULL, NULL);
但它一直被阻止,虽然我认为它必须被唤醒,因为连接完成后服务器发送消息。
好吧,除了 和 之间的阻抗不匹配之外select
,poll
您的问题似乎是
a)您无条件地说要对 websocket 进行轮询以供阅读,并且
b)您永远不会说您有数据要写入网络套接字。
当您获得适当的回调时,您需要对读取和写入 FD 执行(和FD_SET
)FD_CLEAR
操作。你没有那样做。这会导致问题。