如何在不阻塞的情况下以跨平台方式使用Haxe套接字?

osc*_*rcs 5 sockets network-programming haxe

围绕使用带有Haxe工具包的套接字的大多数指南都依赖于线程的使用,这些线程是特定于平台的.这是因为默认情况下套接字会阻塞,这使得它们不适用于许多类型的应用程序,包括游戏.

我知道有一个非阻塞模式,但我无法在不抛出异常的情况下运行它.

如何在不依赖线程的情况下以跨平台方式使用套接字?

osc*_*rcs 7

Sys.net.Socket是主要的套接字实现,适用于八个Haxe目标:Python,Neko,Java,宏,C++,Lua,PHP和C#.

这里提供了以螺纹方式使用这些插座的方法以及进一步的背景.

但是,Haxe文档没有说明套接字如何在非阻塞模式下工作.下面的示例是针对客户端,可能在游戏中使用 - 其他用法应该类似.为此,请创建一个套接字并以常规方式连接它:

var socket = new Socket();

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

成功建立连接,应关闭阻止模式:

socket.setBlocking(false);
Run Code Online (Sandbox Code Playgroud)

然后我们可以使用socket.input从套接字读取,但需要注意我们必须使用try-catch异常处理:

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.
}
Run Code Online (Sandbox Code Playgroud)

由于套接字是非阻塞的,我们必须在循环中调用它.每当我们调用它时,我们将得到一个"操作将阻止"的异常,我们可以忽略它.这个异常用于在我们等待数据时从套接字中取出读取以在循环中执行其他操作.

以类似的方式,我们可以写入套接字:

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) { }
Run Code Online (Sandbox Code Playgroud)

我们也可以做特定的异常处理:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)