Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 482
oscarcs Avatar asked Sep 02 '16 12:09

oscarcs


1 Answers

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);
    }
}
like image 125
oscarcs Avatar answered Jan 03 '23 05:01

oscarcs