有没有办法使用 flash.net.Socket 检测 TCP 连接已被拒绝?

Posted

技术标签:

【中文标题】有没有办法使用 flash.net.Socket 检测 TCP 连接已被拒绝?【英文标题】:Is there a way to detect that TCP connection has been refused using flash.net.Socket? 【发布时间】:2011-03-24 18:12:42 【问题描述】:

有一个使用 flash.net.Socket 连接到服务器的 flash 电影。但是可能存在服务器未运行的情况,因此在连接的端口套接字上没有监听任何内容。

当我执行“telnet 主机名端口”时,我得到一个快速连接被拒绝的错误。但是 flash.net.Socket 不调用任何事件(见下文),而是静默等待套接字超时。对我来说,重要的是尽可能减少检测不存在的服务器所需的时间,以便能够重新连接到集群中的另一台服务器。

我尝试了以下事件,但无济于事:

关闭 连接 ioError 安全错误 套接字数据

在这种情况下,这些都不会被调用。

有没有办法使用 flash.net.Socket 检测 TCP 连接是否被拒绝?

【问题讨论】:

【参考方案1】:

使用 add <img src='http://target:port/' onerror='noconnect' /> 捕获连接错误怎么样?

【讨论】:

所有浏览器都支持onerror吗?当服务器什么都不返回时它会被触发吗? 是的,最好是服务器可以在 GET / 上回复空答案——然后,调用 onsuccess。 w3schools.com/jsref/event_img_onerror.asp -- 看起来所有浏览器都支持 onerror。至少在歌剧/iceweasel/ie 它对我有用。 感谢您的建议,但这似乎只是一种解决方法。我再等一会儿。也许存在真正的解决方案【参考方案2】:

这个呢:

package 
    import flash.display.Sprite;

    public class SocketExample extends Sprite 

        public function SocketExample() 
            var socket:CustomSocket = new CustomSocket("localhost", 80);
        
    


import flash.errors.*;
import flash.events.*;
import flash.net.Socket;

class CustomSocket extends Socket 
    private var response:String;

    public function CustomSocket(host:String = null, port:uint = 0) 
        super(host, port);
        this.timeout=100;
        configureListeners();
    

    private function configureListeners():void 
        addEventListener(Event.CLOSE, closeHandler);
        addEventListener(Event.CONNECT, connectHandler);
        addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
        addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
    

    private function writeln(str:String):void 
        str += "\n";
        try 
            writeUTFBytes(str);
        
        catch(e:IOError) 
            trace(e);
        
    

    private function sendRequest():void 
        trace("sendRequest");
        response = "";
        writeln("GET /");
        flush();
    

    private function readResponse():void 
        var str:String = readUTFBytes(bytesAvailable);
        response += str;
    

    private function closeHandler(event:Event):void 
        trace("closeHandler: " + event);
        trace(response.toString());
    

    private function connectHandler(event:Event):void 
        trace("connectHandler: " + event);
        sendRequest();
    

    private function ioErrorHandler(event:IOErrorEvent):void 
        trace("ioErrorHandler: " + event);
    

    private function securityErrorHandler(event:SecurityErrorEvent):void 
        trace("securityErrorHandler: " + event);
    

    private function socketDataHandler(event:ProgressEvent):void 
        trace("socketDataHandler: " + event);
        readResponse();
    

【讨论】:

它是基于短暂的超时,不是吗?它不适合我,因为有时服务器可能负载很重并且超时时间太短 如果我们要修改服务器架构怎么办?编写外部服务器检查器,它将检查服务器运行状态,并响应云可用性。你怎么看?像 SLA 风格 这个例子是从Adobe doc page逐字复制的,并添加了100ms超时。 timeout 属性仅适用于 Flash 10+,无论如何在这种情况下都无济于事。该示例的问题实际上与我在上面的答案中描述的问题相同:直到构造函数启动连接尝试 after 才会添加侦听器——因此可能会完全错过快速连接错误。您可以通过使用无参数构造函数来避免此问题,然后调用connect(host, port) @Lee 如果您阅读了我之前的评论,我建议通过更改架构级别来解决它,因为在更大的范围内它具有更大的意义。另外,如果你想出了如何以你的方式解决这个问题,欢迎你分享它。谢谢你。 :)【参考方案3】:

关键是监听Socket对象的IOErrorEvent.IO_ERROR事件。在您所指的情况下,连接立即被拒绝,此事件立即触发。事实上,它可以被触发得如此之快以至于你会错过它,除非你按照正确的顺序做事(如此处所示):

// first create the unconnected socket, and add the listener
// you *must* add the listener *before* connecting the socket
//
var mySocket = new Socket();
mySocket.addEventListener(IOErrorEvent.IO_ERROR, function(event:IOErrorEvent):void 
    // called when error occurrs
    trace("ioErrorHandler: " + event);
);
mySocket.addEventListener(flash.events.Event.CONNECT, function(event:Event):void 
    // handle a successful connection here
    //...
);

// now initiate the connection to port 80 on "server.example.com"   
mySocket.connect( 'server.example.com', 80 );

注意:这种方法不是基于超时。如果服务器返回一个明确的“连接被拒绝”响应,那么 IO 错误事件将在收到该响应时立即发生。

超时仅适用于服务器长时间没有返回任何内容的情况。这可能发生在某些服务器/防火墙配置中,实际上丢弃数据包而不是返回“连接被拒绝”。发生这种情况时,客户端(在本例中为 Flash)将等待超时到期。当超时最终到期时,它会像您预期的那样导致IOErrorEvent.IO_ERROR 事件。

默认套接字超时取决于平台,但它总是相当长(~20-30 秒或更长时间)。 Socket.timeout 属性是在 Flash Player 版本 10 和 Air 1.0 中引入的。据我所知,在 Flash Player 10 之前,无法使用 ActionScript 调整套接字超时。

祝你好运!

--- 编辑:如果仍然无法正常工作,请继续阅读 ---

您还应该熟悉 Flash 播放器查找(并要求)套接字策略文件的方式。丢失或损坏的套接字策略文件有时会产生看起来像套接字等待超时的行为。引用this Adobe Document:

默认情况下禁用对套接字和 XML 套接字连接的访问​​,即使套接字 您要连接的域与 SWF 文件位于同一域中。您可以允许套接字级别 通过从以下任何位置提供套接字策略文件进行访问:

端口 843(主策略文件的位置) 与主套接字连接相同的端口 与主套接字连接不同的端口

这意味着,除非您之前使用Security.loadPolicyFile() 加载了策略文件,否则当您最初尝试将套接字连接到服务器时,flash 将首先尝试解析策略文件。在某些情况下,这可能会导致奇怪的连接延迟或其他意外行为。如果您认为您可能会遇到此问题,您应该首先为flash.events.SecurityErrorEvent.SECURITY_ERROR 添加一个侦听器。

【讨论】:

以上是关于有没有办法使用 flash.net.Socket 检测 TCP 连接已被拒绝?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法弄清楚啥是使用 Linux 内核模块?

有没有办法使用“任意”变体作为参数?

有没有办法使用 XCUITest 测试快速操作?

有没有办法使用CSS向后工作[重复]

有没有办法使用CSS向后工作[重复]

有没有办法使用 bookdown 添加章节书目?