How do I use Haxe sockets in a cross-platform way without blocking?
Asked Answered
L

1

6

Most guides surrounding the use of sockets with the Haxe toolkit rely on the use of threads, which are platform-specific. This is because sockets block by default, which makes them unsuitable for many types of applications, including games.

I am aware that there is a non-blocking mode, but I can't get it to function without throwing an exception.

How do I use sockets in a cross-platform way without relying on threading?

Lizarraga answered 2/9, 2016 at 12:31 Comment(2)
With non-blocking mode, there are a few unusual errors that I initially stumbled into too, like eof. I don't have time to make an answer yet, but perhaps look at this code. github.com/5Mixer/mphx/blob/master/mphx/server/impl/… So we have a socket to listen for connections, and then each of these connections handles eof errors etc.Recusancy
I figured out the answer and didn't see it was posted anywhere else, so I wrote the question and answered it myself. That code is very useful for documenting the specific error handling that I glossed over in my answer, however. I'll update it with the info.Lizarraga
L
10

sys.net.Socket is the main socket implementation that works on nine Haxe targets: Python, HashLink, Neko, Java, Macro, C++, Lua, PHP, and C#.

A means of using these sockets in a threaded way, as well as further background, is provided here.

However, the Haxe documentation does not make clear how sockets work in non-blocking mode. The example that follows is for a client, as might be used in a game -- other usages should be similar. To do this, create a socket and connect it in the regular way:

var socket = new Socket();

try
{
    socket.connect(new Host('example.com'), 80);
}
catch (e: Dynamic)
{ 
    // handle connection errors...
}

After a connection is successfully established, blocking mode should be turned off:

socket.setBlocking(false);

We can then use socket.input to read from the socket, with the caveat that we have to use try-catch exception handling:

var out: String = '';
try
{
    // could also use .input.readByte(), .input.readDouble() etc.
    // .read() doesn't work, however.
    out = socket.input.readLine();
}
catch (e: Dynamic) // catch all types of errors
{ 
    // can handle specific types of exceptions here.
}

Since the socket is non-blocking we will have to call this in a loop. Every time we call this, we will get an 'operation will block' exception that we can ignore. This exception is used to break out of reading from the socket to do other things in the loop while we wait for data.

In a similar fashion, we can write to the socket:

var msg: String = 'hello world!\r\n';
try
{
    // could also use socket.write(msg) or socket.output.writeByte() etc...
    socket.output.writeString(msg);
}
catch (e: Dynamic) { }

We can also do specific exception handling:

catch (e: Dynamic)
{
    // end of stream
    if (Std.is(e, haxe.io.Eof) || e == haxe.io.Eof)
    {
        // close the socket, etc.
    }
    else if (e == haxe.io.Error.Blocked)
    {
        // not an error - this is still a connected socket.
        break;
    }
    else
    {
        trace(e);
    }
}
Lizarraga answered 2/9, 2016 at 13:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.