【问题标题】:AS3 Socket ProcessEvent.SOCKET_DATA seems not triggeredAS3 Socket ProcessEvent.SOCKET_DATA 似乎没有被触发
【发布时间】:2014-03-13 04:28:28
【问题描述】:

我们使用 AS3 Event:ProcessEvent.SOCKET_DATA 来监听套接字数据。 所以这是我的套接字数据句柄的 AS3 代码。

private function packetHandler( e:ProgressEvent ):void
    {
        while( m_socket.bytesAvailable && m_socket.bytesAvailable >= pLen )
        {
            //pLen means the packet length
            //pLen init is zero
            if( pLen == 0 )
            {
                //PACKET_LEN stands for the solid length of one packet
                //PACKET_LEN = HEAD_LEN + 4
                //the 4 means an unsigned int which means the packet content length
                if( m_socket.bytesAvailable > PACKET_LEN )
                {
                    m_socket.readBytes(  headByteBuffer, 0, HEAD_LEN );
                    headByteBuffer.clear();
                    pLen = m_socket.readUnsignedInt() + 4;
                }
                else
                {
                    break;
                }
            }
            //recieved a whole packet now handle it
            else
            {
                var newPacket:ByteArray = new ByteArray();
                
                newPacket.endian = Endian.LITTLE_ENDIAN;
                m_socket.readBytes( newPacket, 0, pLen );
                
                parasMsg( newPacket, pLen-4 );
                pLen = 0;
            }
        }
    }

这张图片可以描述一个完整的数据包:

我的问题是:当 Flash 收到一个不完整的数据包并触发句柄时。 但是包的左边部分永远不会触发句柄,看起来包的左边部分已经丢失了!!!

我用了一个抓包工具,发现tcp数据包没问题,但是为什么左边部分没有再次触发事件?

您可以在下面获得更多调试信息。谢谢!

这是我的日志:

  • byteava 表示 m_socket 的 bytesAvailable

==>sendPacket: {"rangeID":"1","uid":"145962","serviceType":"copyscene","cmd":"CopySceneMoveAsk","pathPoint":[{"col" :7,"row":6},{"col":7,"row":5},{"col":7,"row":4},{"col":7,"row":3 },{"col":6,"row":3}],"sn":"79","smallPathPoint":[[22,19],[22,18],[22,17],[22 ,16],[22,15],[22,14],[22,13],[21,13],[21,12],[21,11],[20,11],[20,10 ]]}, bytesLoaded = 463

ProgressEvent Triggered!0 socket byteava = 373 evt load:373 evt total:0 evt:[ProgressEvent type="socketData" bubbles=false cancelable=false eventPhase=2 bytesLoaded=373 bytesTotal=0]

从socket中找一个包,pLen=288 socket byteava = 276

ProgressEvent Triggered!288 socket byteava = 441 evt load:165 evt total:0 evt:[ProgressEvent type="socketData" bubbles=false cancelable=false eventPhase=2 bytesLoaded=165 bytesTotal=0]

开始读取数据包到缓冲区,pLen=288 socket byteava = 441

整个数据包内容:读取一个数据包到缓冲区,pLen=288 socket byteava = 153

服务器数据包内容字节缓冲区 ava:288 len:288 pos: 0

服务器参数数据:数据长度:284 数据内容:{"cmd":"CopySceneMoveNotify","gtcmd":"108","layer":"1","pathPoint":[{"col":7 ,"row":6},{"col":7,"row":5},{"col":7,"row":4},{"col":7,"row":3}, {"col":6,"row":3}],"smallPathPoint":[[22,19],[22,18],[22,17],[22,16],[22,15], [22,14],[22,13],[21,13],[21,12],[21,11],[20,11],[20,10]HTTP/1.1 200

_[20,10]HTTP/1.1 200_这就是问题所在!!带有另一个包头的不完整包猫。

以下是 TCP 连接的捕获:

希望你能投票,这样我就可以把这个问题的照片放在上面!

我的英文不是很好,希望你能明白我的意思。 谢谢!

【问题讨论】:

  • 为什么e的类型是ProgressEvent?
  • ProgressEvent.SOCKET_DATA
  • 我几乎可以肯定问题出在 packetHandler 中,尤其是在使用过程中。我的游戏是服务器/客户端,通信是通过套接字进行的,从来没有这样的问题。我也差不多如果你改变 m_socket.readBytes(newPacket, 0, pLen);到 m_socket.readBytes(newPacket, 0, m_socket.bytesAvailable);您将收到没有 HTTP/1.1 200_ 的消息
  • 但是让我看到的是 ProgressEvent.SOCKET_DATA 没有被触发(所以它不会进入 while 循环),并且一个数据包的不完整部分似乎丢失了,因为它与另一个数据包的标题相匹配。
  • m_socket 中的bytesAvailable 有时不能是一个完整的数据包,所以如果我收到一个数据包的一半,我会将数据留在套接字缓冲区中。当收到整个数据包时,我将处理数据包并从套接字缓冲区读取数据包。

标签: actionscript-3 sockets


【解决方案1】:

Socket 的事件 flash.events.ProgressEvent.SOCKET_DATA 将在您接收到数据时触发,此时您可以获得接收到的字节(检查 .bytesAvailable )。当味精被分成多个包时,您将收到每个包的事件。 在您的情况下,检查 m_socket.bytesAvailable >= pLen 时 pLen 的值可能有误。

我假设您在请求消息时发送了消息大小(在这种情况下,您可以检查是否收到了整个消息)。在这种情况下,您必须有一个类成员(ByteArray)作为保存接收到的字节的缓冲区。当新数据到来时,您必须将新字节复制到该成员,然后检查您是否收到整个消息。如果缓冲区包含整个味精而不是从中删除味精。 一般来说,您的事件处理程序必须如下所示:

protected function onSocketData( pEvt: Event ): void
{
    try
{
       if ( 0 < pEvt.target.bytesAvailable )
       {
    var byteStream: ByteArray = new ByteArray();            
    pEvt.target.readBytes( byteStream, 0, Socket( pEvt.target ).bytesAvailable );
    // Append readed data to your buffer

    do 
    {
        //Check if you have enough bytes to read whole msg and execute it
                    //do..while because maybe it can be more than one msg in buffer

    }
    while ( null != msgContent );
    }
}
catch ( exc )
{

}

}

【讨论】:

  • pLen 正常。我们可以使用套接字自己的缓冲区来做到这一点。
  • 问题是一个完整的数据包的左边没有触发 SOCKET_DATA 事件。我很快就会给你看。
【解决方案2】:

问题应该是由数据包的可靠标头引起的。

以下是数据包的 93​​ 字节实心标头。

private static const HTTP_RESPONSE_CONTENT : String = "HTTP/1.1 200 OK \r\n"
        + "Connection: keep-alive \r\n"
        + "Content-Length: 280 \r\n"
        + "Content-Type: text/html \r\n\r\n";

此标头将位于每个数据包的标头中,AS3 可以将其视为http,并可能使用Content-Length: 280 切断流。所以 280 字节的左边部分永远不会触发 SOCKET_DATA 事件。

当我删除此标头时,现在可以了。

【讨论】:

    猜你喜欢
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多