You are trying to push water up hill.
Caveat: I've only written a server that does this, not a client; however, the interface is very similar
Firstly, libwebsockets
is written on the basis you will use poll
or ppoll
rather than select
. I'm sure it's possible to use select
, but your life will be much easier if you use poll
or ppoll
; rewriting my select()
code to use ppoll
took about 10 minutes. If you really want to use select
, I suggest you get external polling working using ppoll
, then rewrite to use select()
.
Next, look at test-server.c
, and specifically how the code changes if EXTERNAL_POLL
is defined. You also want to read this bit of the API documentation:
The next four reasons are optional and only need taking care of if you will be integrating
libwebsockets sockets into an external polling array.
LWS_CALLBACK_ADD_POLL_FD
libwebsocket deals with its poll loop internally, but in the case you are integrating with another
server you will need to have libwebsocket sockets share a polling array with the other server. This
and the other POLL_FD related callbacks let you put your specialized poll array interface code in
the callback for protocol 0, the first protocol you support, usually the HTTP protocol in the
serving case. This callback happens when a socket needs to be added to the polling loop in contains the fd, and len is the events bitmap (like, POLLIN). If you are using the internal polling loop (the "service" callback), you can just ignore these callbacks.
LWS_CALLBACK_DEL_POLL_FD
This callback happens when a socket descriptor needs to be removed from an external polling array. in is the socket desricptor. If you are using the internal polling loop, you can just ignore it.
LWS_CALLBACK_SET_MODE_POLL_FD
This callback happens when libwebsockets wants to modify the events for the socket descriptor in
in. The handler should OR len on to the events member of the pollfd struct for this socket
descriptor. If you are using the internal polling loop, you can just ignore it.
LWS_CALLBACK_CLEAR_MODE_POLL_FD
This callback occurs when libwebsockets wants to modify the events for the socket descriptor in in.
The handler should AND ~len on to the events member of the pollfd struct for this socket
descriptor. If you are using the internal polling loop, you can just ignore it.
What this is saying (simply put) is that libwebsockets will call you with these methods and ask you to manipulate your poll
array.
Ignoring some complications about locking, you can see test-server.c
has them implemented thus:
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;
I don't believe (sever side) you need to implement the second two callbacks, test-server.c
does not, and I do not.
After you call poll
, you need to request libwebsockets
to service its own FDs, like so (again from 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;
So, let's go back to your specific questions:
So i tried below steps.
Connect websocket through struct libwebsocket *wsi = libwebsocket_client_connect(..)
I did also check if the reture value is NULL or not for error.
Get file descriptor through int fd = libwebsocket_get_socket_fd(wsi);
FD_SET(fd, &readFd);
and select(maxFd + 1, &readFd, NULL, NULL, NULL);
But it keeps being blocked, though i think it must be wake up since server send message after connection is completed.
Well, apart from the impedance mismatch between select
and poll
, your problem here would appear to be that
a) you are unconditionally saying the websocket is to be polled for reading, and
b) you are never saying you have data to write to the web socket.
You need to do FD_SET
(and FD_CLEAR
) on both the read and write FDs as and when you get the appropriate callbacks. You are not doing that. This will cause problems.