简体   繁体   English

如何使用Haxe SSL Socket?

[英]How to use Haxe SSL Socket?

I'm trying to setup an https server but I can't find any example on how to use Haxe sys.ssl.Socket and the documentation doesn't quite speak to me. 我正在尝试设置一个https服务器,但我找不到任何关于如何使用Haxe sys.ssl.Socket ,文档并没有完全对我说。

So far I got the following code which throw an 'Access violation'. 到目前为止,我得到了以下代码,引发了“访问冲突”。

var _aSocketDistant = new List<Socket>();

var _oSocketMaster =  new SocketSSL();
_oSocketMaster.setCA(Certificate.loadFile('ssl/homeplanet.pem'));
_oSocketMaster.setCertificate( 
    Certificate.loadFile('ssl/homeplanet.pem'), 
    Key.loadFile('ssl/homeplanet.key', false, 'homeplanet') 
);
_oSocketMaster.setHostname('localhost');

_oSocketMaster.bind( new Host( 'localhost' ), 8000);
_oSocketMaster.setBlocking( false );
_oSocketMaster.listen( 9999 );

while(true) {

    // Accepting socket
    var oSocketDistant = _oSocketMaster.accept();
    if ( oSocketDistant != null ) {
        trace( 'opening : ' + oSocketDistant.peer() );
        oSocketDistant.setBlocking( false );
        _aSocketDistant.add( oSocketDistant );
    }

    // Trying to read from each socket 
    for ( oSocketDistant in _aSocketDistant ) {
        try {
            Sys.print( oSocketDistant.input.readString(1) );
        } catch ( e :Dynamic ) {
            if ( e != Error.Blocked )
                throw e;
        }
    }
}

This give me the following result : 这给了我以下结果:

Uncaught exception: Access violation
Called from sys.ssl.Socket.accept(D:\HaxeToolkit4\haxe\std/hl/_std/sys/ssl/Socket.hx:203)
Called from $Main.main(Main.hx:39)
Called from fun$517(?:1)

The key/certificate files where generated using this tutorial . 使用本教程生成的密钥/证书文件。

Am I using the socket correctly ? 我正确使用插座吗?

Ok, I decided I wanted to test Haxe SSL sockets myself. 好吧,我决定自己想测试Haxe SSL套接字。 Due to lots of caveats, this will probably not be an answer for your problem, but maybe some of the tidbits will help. 由于很多警告,这可能不是你的问题的答案,但也许一些花絮将有所帮助。 And starting from "something that works" is better than nothing! 从“有效的东西”开始,总比没有好!

First, I'm on Linux. 首先,我在Linux上。 I've found that sockets (and threads) can exhibit different behaviors and problems on Windows than on Linux / OSX. 我发现套接字(和线程)在Windows上可能会出现与Linux / OSX不同的行为和问题。

Second, I'm first trying this with a valid hostname. 其次,我首先尝试使用有效的主机名。 I've never used SSL on localhost , and wanted to remove all unknowns. 我从来没有在localhost上使用SSL,并希望删除所有未知数。 So I happen to have a valid cert/key that I'm using. 所以我碰巧有一个我正在使用的有效证书/密钥。 In the code below, it's referred to as foo.example.com . 在下面的代码中,它被称为foo.example.com You can get a free cert for a domain you own at letsencrypt.org . 您可以在letsencrypt.org获得您拥有的域名的免费证书。

Third, I ran into an issue in the Haxe std library. 第三,我在Haxe std库中遇到了一个问题 To get around it, I simply changed line 17 in haxe/std/cpp/_std/sys/ssl/Key.hx : 为了解决这个问题,我只是在haxe/std/cpp/_std/sys/ssl/Key.hx更改了第17行:

var str = data.toString(); // cpp.Lib.stringReference(data);

Fourth, I have no idea about the "access violation" problem. 第四,我不知道“访问违规”问题。 That's gonna be Windows-specific, likely. 这可能是特定于Windows的。 I would have guessed perhaps a permissions or firewall problem, but googling "Windows socket access violation", I see lots of random discussion. 我可能已经猜到了权限或防火墙问题,但谷歌搜索“Windows套接字访问违规”,我看到很多随机的讨论。

Finally, I'm not sure your non-blocking sockets with while-loops is a good idea. 最后,我不确定你的带有while循环的非阻塞套接字是个好主意。 Maybe it could be done that way... but I've always had better luck with blocking sockets and threads (again, threads may behave better on 'nix than Windows.) 也许它可以通过这种方式完成......但是我一直有更好的运气来阻止套接字和线程(同样,线程可能在'nix上比Windows更好。)

Note: If you do work with non-blocking sockets, sometimes you have to catch / ignore both haxe.io.Error.Blocked and haxe.io.Error.Custom(Blocked) . 注意:如果您使用非阻塞套接字,有时您必须捕获/忽略haxe.io.Error.Blockedhaxe.io.Error.Custom(Blocked) An irritation, but meh. 一种恼怒,但是...... Use this: 用这个:

  try { Sys.print( oSocketDistant.input.readString(1) ); } catch ( e:haxe.io.Error ) { switch e { case haxe.io.Error.Blocked: // no problem case haxe.io.Error.Custom(c) if (c==haxe.io.Error.Blocked): // no problem default: throw e; } } catch ( e:haxe.io.Eof ) { trace('Got Eof'); } 

It's more efficient to use threads with blocking sockets. 使用带有阻塞套接字的线程更有效。 That way, the thread simply sleeps until the socket wakes it up. 这样,线程只是休眠,直到套接字唤醒它。 Which is what you want, so the CPU isn't spinning in a while loop, endlessly checking for unblocked sockets. 这是你想要的,所以CPU不会在while循环中旋转,无休止地检查未阻塞的套接字。

So I've modified your code a bit. 所以我稍微修改了你的代码。 My example uses the main thread to accept connections, and then passes the socket off to a reader thread. 我的示例使用主线程接受连接,然后将套接字传递给读取器线程。 The reader thread prints anything received (like your example), and then exits on Eof . 读者线程打印收到的任何内容(如您的示例),然后退出Eof

import sys.net.Host;
import sys.net.Socket;
import sys.ssl.Socket as SocketSSL;
import sys.ssl.Certificate;
import sys.ssl.Key;

import cpp.vm.Mutex;
import cpp.vm.Thread;

class Main
{
  static var _mutex:Mutex = new Mutex();

  public static function main()
  {
    var _oSocketMaster =  new SocketSSL();
    var cert = Certificate.loadFile('my_chain.pem');
    _oSocketMaster.setCA(cert);
    _oSocketMaster.setCertificate(cert, 
                                  Key.loadFile('my_key.key'));
    _oSocketMaster.setHostname('foo.example.com');

    // e.g. for an application like an HTTPs server, the client
    // doesn't need to provide a certificate. Otherwise we get:
    // Error: SSL - No client certification received from the client, but required by the authentication mode
    _oSocketMaster.verifyCert = false;

    // Binding 0.0.0.0 means, listen on "any / all IP addresses on this host"
    _oSocketMaster.bind( new Host( '0.0.0.0' ), 8000);
    _oSocketMaster.listen( 9999 );

    while(true) {

      // Accepting socket
      trace('waiting to accept...');
      var oSocketDistant:SocketSSL = _oSocketMaster.accept();
      if ( oSocketDistant != null ) {
        trace( 'got connection from : ' + oSocketDistant.peer() );
        oSocketDistant.handshake(); // This may not be necessary, if !verifyCert

        // Spawn a reader thread for this connection:
        var thrd = Thread.create(reader);
        trace('sending socket...');
        thrd.sendMessage(oSocketDistant);
        trace('ok...');
      }

    }
  }

  static function reader()
  {
    var oSocketDistant:sys.net.Socket = cast Thread.readMessage(true);
    trace('new reader thread...');

    while(true) {

      try {
        Sys.print( oSocketDistant.input.readString(1) );
      } catch ( e:haxe.io.Eof ) {
        trace('Eof, reader thread exiting...');
        return;
      } catch ( e:Dynamic ) {
        trace('Uncaught: ${ e }'); // throw e;
      }
    }
  }
}

So, let's see it in action! 所以,让我们看看它在行动!

I compile and start the above server in one terminal: 我在一个终端编译并启动上面的服务器:

> haxe -main Main -debug -cpp out && ./out/Main-debug
...compiling info removed...
Main.hx:37: waiting to accept...

And then I connect from another terminal with a client that's a command line utility for testing ssl connections: 然后我从另一个终端与客户端连接,该客户端是用于测试ssl连接的命令行实用程序:

> openssl s_client -connect foo.example.com:8000
...lots of info about the cert...
SSL handshake has read 3374 bytes and written 370 bytes
Verification: OK
---

And it hangs there, waiting for you to type input. 它挂在那里,等着你输入输入。 On the server side we see: 在服务器端,我们看到:

Main.hx:38: got connection from : { host => Host, port => 57394 }
Main.hx:43: sending socket...
Main.hx:45: ok...
Main.hx:35: waiting to accept...
Main.hx:54: new reader thread...

We can open many clients in separate terminals, they each get their own reader thread. 我们可以在不同的终端中打开许多客户端,每个客户端都有自己的读者线程。 Typing messages into the client terminals show up in the server terminal, so the reader threads are working. 在客户终端中键入消息显示在服务器终端中,因此读取器线程正在工作。

On the client, CTRL+C to exit, and on the server we see: 在客户端上, CTRL + C退出,在服务器上我们看到:

Main.hx:61: Eof, reader thread exiting...

Everything is working as expected! 一切都按预期工作!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM