播放Flash视频时检测TCP连接是否关闭

时间:2011-02-15 23:21:55

标签: flash actionscript-3 video tcp

在Flash客户端,如何检测服务器何时故意关闭与其视频流的TCP连接?发生这种情况时我需要采取措施 - 可能会尝试重新启动视频或显示错误消息。目前,连接关闭和连接缓慢对我来说是一样的。在这两种情况下,NetStream对象都会引发NetStream.Play.Stop事件。当连接速度很慢时,它通常会在几秒钟内自行恢复。我希望只在连接关闭时采取行动,而不是在连接缓慢时采取行动。

以下是我的常规设置的样子。这是基本的NetConnection - > NetStream - > Video设置。

this.vidConnection = new NetConnection();
this.vidConnection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, this.connectionAsyncError);
this.vidConnection.addEventListener(IOErrorEvent.IO_ERROR, this.connectionIoError);
this.vidConnection.addEventListener(NetStatusEvent.NET_STATUS, this.connectionNetStatus);
this.vidConnection.connect(null);
this.vidStream = new NetStream(this.vidConnection);
this.vidStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, this.streamAsyncError);
this.vidStream.addEventListener(IOErrorEvent.IO_ERROR, this.streamIoError);
this.vidStream.addEventListener(NetStatusEvent.NET_STATUS, this.streamNetStatus);
this.vid.attachNetStream(this.vidStream);

当服务器关闭TCP或连接冻结时,不会触发任何错误事件。只有NetStream.Play.Stop事件触发。以下是从最初播放视频到TCP连接关闭所发生的情况。

connection net status = NetConnection.Connect.Success
playStream(http://192.168.0.44/flv/4d29104a9aefa)
NetStream.Play.Start
NetStream.Buffer.Flush
NetStream.Buffer.Full
NetStream.Buffer.Empty
checkDimensions 0 0
onMetaData
NetStream.Buffer.Full
NetStream.Buffer.Flush
checkDimensions 960 544
NetStream.Buffer.Empty
NetStream.Buffer.Flush
NetStream.Play.Stop

当我在连接关闭和连接缓慢期间对各种属性进行转储时,我看不到可以帮助我区分结束和缓慢的独特值。

NetConnection->connected = true
NetConnection->connectedProxyType = none
NetConnection->proxyType = none
NetConnection->uri = null
NetConnection->usingTLS = false
VidStream->bufferLength = 0
VidStream->bufferTime = 0.1
VidStream->bytesLoaded = 3204116
VidStream->bytesTotal = 3204116
VidStream->currentFPS = 0
VidStream->time = 63.797

3 个答案:

答案 0 :(得分:4)

除了“NetStream.Failed”之外,我不知道发出连接断开的任何事件,只能与Flash Media Server一起使用(我甚至不知道是否或何时被解雇)

你必须找到一个基于“NetStream.Buffer.Empty”的解决方案:每当发生此事件时启动一个计时器,让它等待足够长的时间以确保连接不可能恢复,然后启动一个新的尝试。您可以在每个“NetStream.Buffer.Full”上重置计时器,或者在电影结束或手动暂停时重置计时器,这样除非确实需要,否则不会造成任何伤害。

答案 1 :(得分:2)

使用NetConnection状态而不是:NetConnection.Connect.Closed

我遇到了类似的问题&注意到视频连接失败时会截断NetStream.bytesTotal值。因此,根据NetStream捕获视频长度(以字节为单位)以&在调用NetConnection.Connect.Closed时使用它来检测故障。

因为视频代码无法在上下文中解释,所以我将它放在一起,建立在Flash的示例@ Flash NetConnection Example

以下是代码,内联评论:

public class NonTruncatedNetConnectionExample extends Sprite {
    private var videoURL:String = "http://www.helpexamples.com/flash/video/cuepoints.flv";
    private var connection:NetConnection;
    private var stream:NetStream;
    private var video:Video = new Video();
    // ADDITION: special length variable to check for truncation
    private var videoBytes:uint;

    public function NonTruncatedNetConnectionExample() {
        connection = new NetConnection();
        connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
        connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
        connection.connect(null);
    }

    private function netStatusHandler(event:NetStatusEvent):void {
        switch (event.info.code) {
            case "NetConnection.Connect.Success" :
                connectStream();
                break;
            case "NetStream.Play.StreamNotFound" :
                trace("Stream not found: " + videoURL);
                break;
            // ADDITION: this will be triggered when the connection is closed
            // on completion, or on failure
            case "NetConnection.Connect.Closed" :
                if (this.videoBytes != this.stream.bytesTotal) {
                    // failure
                    // you can throw the error here
                    // or in the loadingProgress function below
                } else {
                    // success
                    // the video loaded completely
                }
                break;
        }
    }

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

    private function connectStream():void {
        var stream:NetStream = new NetStream(connection);
        stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
        stream.client = new CustomClient();
        video.attachNetStream(stream);
        stream.play(videoURL);
        addChild(video);
        // ADDITION: the loadingProgress function
        this.addEventListener(Event.ENTER_FRAME, loadingProgress);
    }

    /***
    ** ADDITION : loadingProgress captures the length of the video in bytes for use in comparison when
    ** NetConnection.Connect.Closed is called
    ** It also tracks current loading progress so you can use it as a buffer indicator
    */
    private function loadingProgress(E:Event):void {
        // check that this.stream.client has initialised & you have correct access to this.stream variables
        // bytesTotal is also a divisor so must be greater than 0 before continuing, or it will hard-fail
        if (this.stream.client && this.stream.bytesTotal > 0) {
            // sanity checker ;)
            trace("bytesLoaded = " + this.stream.bytesLoaded + " :: bytesTotal = " + this.stream.bytesTotal);
            // capture the video's total bytes only if the variable does not yet exist
            // before this point this.stream.bytesTotal returns a bogus (really big) number
            // watch out for capturing this.stream.totalBytes before this point, or you create a double negative,
            // because it won't match the actual bytesTotal & will therefore error [ it got me :( ; but then I got it ;) ]
            if (!this.videoBytes) this.videoBytes = this.stream.bytesTotal;
            // compare this to stream.totalBytes to detect truncation
            if (this.videoBytes != this.stream.bytesTotal) {
                // error
                // you can throw the error here if you want, or wait for the NetConnection.Connect.Closed switch above
            } else {
                // or you can detach this event listener here while just holding on to the videoBytes variable
                // & wait for the NetConnection.Connect.Closed switch above
                // e.g. this.removeEventListener(Event.ENTER_FRAME, loadingProgress);
            }
            // use this to drive a buffer bar if you want
            var radian:Number = (this.stream.bytesLoaded / this.totalBytes);
            var percent:Number = radian * 100;
        }
    }

}

还有:

class CustomClient {
    public function onMetaData(info:Object):void {
        trace("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);
    }
    public function onCuePoint(info:Object):void {
        trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
    }
}

答案 2 :(得分:1)

在Windows上使用NetLimiter进行密集测试(意外地“终止”TCP连接)后,只会触发NetStream.Buffer.Empty。

解决方案weltraumpirat为您提供了唯一可用的解决方案(启动计时器以查看您是否仍在主动接收数据)。

显然,丢失所有TCP连接后,URLStream :: connected仍然为真,并且停止(没有任何IO_ERROR或其他事件/异常,就像NetStream一样)。 如果您的目标是> 10.1 Flash,您可以使用URLStream将数据加载到NetStream :: appendBytes中(请参阅数据生成模式的文档(通过将null传递给NetStream :: play()来启用)),然后,当接收NetStream.Buffer.Empty时,立即检查URLStream :: connected以查看您是否仍然连接到服务器,而不是启动Timer。