Sockets

218 views
Skip to first unread message

Mark Sibly

unread,
Dec 4, 2017, 8:21:35 PM12/4/17
to emscripten-discuss
Hi,

I am completely  new to emscipten sockets and am wondering how they work and what to expect.

I understand they are built on top of websockets, but I always thought websockets were SendMsg/RecvReply based - how does that work?

Do you have to use threads if you want to 'block' on an emscripten socket without blocking the entire app? Is this recommended or is it best to just 'poll' via, say, ioctlsocket with FIONREAD. Can you poll with select?

Should I at least be able to connect to TCP port 80 of my http website? I have so far been unable to perform a simple connect and wonder if it's even possible? I'm not expecting to be able to perform an http GET - although perhaps that is possible?

My connect code is ipv6-ish, ie:

 int _connect( const char *hostname,const char *service ){

addrinfo hints;
memset( &hints,0,sizeof( hints ) );

hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_STREAM;
hints.ai_protocol=IPPROTO_TCP;
if( hostname && !hostname[0] ) hostname=0;

addrinfo *pres=0;
if( ::getaddrinfo( hostname,service,&hints,&pres ) ) return -1;
int sock=-1;
for( addrinfo *res=pres;res;res=res->ai_next ){
sock=::socket( res->ai_family,res->ai_socktype,res->ai_protocol );
if( sock==-1 ) continue;

if( !connect( sock,res->ai_addr,res->ai_addrlen ) ) break;
::closesocket( sock );
sock=-1;
}
freeaddrinfo( pres );
return sock;
}

This works on windows, macos and linux (ie: I can connect any TCP port 80) but not emscripten - the connect always fails. Should I revert to the pre-ipv6 way of connecting? I did give this a quick try but with no luck.

Any clues most welcome!

Bye,
Mark Sibly




Александр Гурьянов

unread,
Dec 4, 2017, 10:00:20 PM12/4/17
to emscripte...@googlegroups.com
I've use linux sockets with emscripten. They work as in native code except one thing - they should be async. So if you app use async socket then it should work out the box. Ofcourse you should wrap server socket with websockify it's work like a charm.

5 дек. 2017 г. 8:21 ДП пользователь "Mark Sibly" <blitz...@gmail.com> написал:
--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mark Sibly

unread,
Dec 5, 2017, 4:12:06 AM12/5/17
to emscripten-discuss
Thanks for the reply, good to know at least someone has them working!

Does my connect code look OK?

How should the hostname look?

If I use "monkeycoder,co.nz" I am getting errno=115 ('in progress') after connect fails.

If I use "http://monkeycoder.co.nz" I am getting errno=113 ('no route to host') after connect fails.

I have also tried "ws://demos.kaazing.com" and "demos.kaazing.com" with the same result.

What is 'websockify'? At this point, I'm not actually trying to send/receive data, just trying to connect. Will I need websockify for this? I am on Windows 10, does websockify even run on this?

Floh

unread,
Dec 5, 2017, 8:11:19 AM12/5/17
to emscripten-discuss
Here's a quick'n'dirty example client which works across emscripten/Windows/OSX/Linux: 


This assumes that messages are text and separated by a '\r'.

The only interesting parts are (a) the socket must be non-blocking, also during connecting, and (b) uses select to check if the socket is ready for reading and writing

On the server side you need to use WebSocket proxy which the emscripten client connects to (so you need 2 ports if you want both native and HTML5 clients to connect, one "raw" TCP port for the native clients, and one WebSocket port for the HTML5 clients).

Websockify is such a proxy solution, but I used a Go server with Gorilla websocket instead (http://www.gorillatoolkit.org/pkg/websocket)

The main difference between TCP and WebSocket is that WebSocket does message-framing (so one send will result in one recv with the complete data on the other side, while in TCP you send and receive a stream of data and need to re-assemble complete messages on the other side).

If you want a solution that works both native and with HTML5 I would recommend to ignore the WebSocket message framing and treat both ends like a normal TCP stream (with your own message framing).

You should also give HumbleNet a try, I haven't used this yet because it was a bit too late: https://github.com/HumbleNet/HumbleNet

Cheers,
-Floh.

Mark Sibly

unread,
Dec 5, 2017, 2:40:50 PM12/5/17
to emscripte...@googlegroups.com
Thanks very much for that, although I can't actually build/test it - NetClientSetup at least is missing.

It did inspire me to add set the socket O_NONBLOCK flag in my own code, but it doesn't seem to help, I'm still get errno 15 'in progress' error.

But looking at your code, doConnect() actually appears to treat connect errors as successes if the error happened to be 'in progress' (and others)! In fact, doConnect *only* succeeds if it fails!

I guess that sort of makes sense, but I am feeling quite out of my depth here and aren't really sure how to proceed. I am having trouble picturing the exact setup (servers, websockify? etc) involved in simply allowing 2 players to be able to play against each other online, which is all I really want to achieve. Do I need websockify for this? What does the sever run? etc.




To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "emscripten-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/emscripten-discuss/3oyVuc8kY2c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to emscripten-discuss+unsub...@googlegroups.com.

Александр Гурьянов

unread,
Dec 6, 2017, 12:21:41 AM12/6/17
to emscripte...@googlegroups.com
I've use common internet address like '192.168.0.104:7014' and connect
to socket in this way:

int flags;
if ((flags = fcntl(socketId, F_GETFL, 0)) < 0) {
abort();
}
if (fcntl(socketId, F_SETFL, flags | O_NONBLOCK) < 0) {
abort();
}


if (socketId >= 0) {
if (connect(socketId, aip->ai_addr, aip->ai_addrlen) < 0) {
if (errno != EINPROGRESS) {
return false;
}
}
return;
}

abort();


After socket is connected I send and receive data in this way:

fd_set fdr;
fd_set fdw;
int res;

FD_ZERO(&fdr);
FD_ZERO(&fdw);
FD_SET(loader->socketId, &fdr);
FD_SET(loader->socketId, &fdw);
res = select(64, &fdr, &fdw, NULL, NULL);

and then I use write(socketId, buf, num) or read(socketId, buf, num)
depends on flags and protocol logic.

This socket code will work in native envrinoment on linux. So I can
test client/server communication through native tools (debugger).
After that when client and server works fine I go to next step,
running websockfiy. For example native server works on port 7014, then
I start proxing this port with websockify to 7015:

websockify -v 192.168.0.104:7014 192.168.0.104:7015

Emscripten version will work on 7015 port (you should connect to 7015
in emscripten version and to 7014 in native version). Usually this
steps is enough to get worked solution.


P.S. For nonblocking mode is correct to get EINPROGRESS it's expected behaviour.
>>>>> an email to emscripten-disc...@googlegroups.com.
>>>>> For more options, visit https://groups.google.com/d/optout.
>>
>> --
>> You received this message because you are subscribed to a topic in the
>> Google Groups "emscripten-discuss" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/d/topic/emscripten-discuss/3oyVuc8kY2c/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to
>> emscripten-disc...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "emscripten-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to emscripten-disc...@googlegroups.com.

Александр Гурьянов

unread,
Dec 6, 2017, 12:22:48 AM12/6/17
to emscripte...@googlegroups.com
Sorry I miss first line in connection snippet:

printf("SocketLoader trying to connect protocol(%d) socktype(%d)
'%s'\n", aip->ai_socktype, aip->ai_protocol, socketAddress.c_str());
socketId = socket(aip->ai_family, aip->ai_socktype /*|
SOCK_NONBLOCK*/, aip->ai_protocol);

int flags;
if ((flags = fcntl(socketId, F_GETFL, 0)) < 0) {
abort();
}
if (fcntl(socketId, F_SETFL, flags | O_NONBLOCK) < 0) {
abort();
}


if (socketId >= 0) {
if (connect(socketId, aip->ai_addr, aip->ai_addrlen) < 0) {
if (errno != EINPROGRESS) {
return false;
}
}
return;
}

abort();

Floh

unread,
Dec 6, 2017, 1:58:04 AM12/6/17
to emscripten-discuss
Things like "EINPROGRESS" or "EWOULDBLOCK" are not actually errors, but like status reports of the non-blocking socket that it doesn't have anything useful to report yet because an asynchronous operation is still in progress. E.g. when connecting on a non-blocking, the connect() function will most likely return immediately with a SOCKET_ERROR and EINPROGRESS, this means the connection process is underway. At some later time, the select() call will return that writing is possible, this means the connection has finished and the socket is ready for operation.

Those details for non-blocking socket are a bit hidden in the documentation (e.g. http://man7.org/linux/man-pages/man2/connect.2.html).

I think your best bet is to integrate HumbleNet, since it should hide all those details under a more convenient interface.

Cheers,
-Floh
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Mark Sibly

unread,
Dec 6, 2017, 1:50:44 PM12/6/17
to emscripte...@googlegroups.com
Thanks for everyone's help with this. I've never actually used non-blocking sockets before so that side of things is new to me, but I'm pretty sure with all the adivce and examples posted here I'll be able to get things/something working now. Websockify sounds like it'll be very useful here too.

> I think your best bet is to integrate HumbleNet, 

I want to get 'real' sockets going as my project is a programming language that translates to c++ (and emscripten) and I want to provide users with something as much like 'normal' sockets as possible.

But once I do get sockets going, I might look into adding HumbleNet as a 'module'.


To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "emscripten-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/emscripten-discuss/3oyVuc8kY2c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages