1

我们使用 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;
            }
        }
    }

这张图片可以描述一个完整的数据包: http://wuzhiwei.net/problems/packet.gif

我的问题是:当 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 已触发!0 套接字 byteava = 373 evt 已加载:373 evt 总计:0 evt:[ProgressEvent type="socketData" bubbles=false cancelable=false eventPhase=2 bytesLoaded=373 bytesTotal=0]

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

ProgressEvent 触发!288 套接字 byteava = 441 evt 加载:165 evt 总计: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_这就是问题所在!!带有另一个数据包标头的不完整数据包 cat。

这是 TCP 连接的捕获: http://wuzhiwei.net/problems/captured_pa​​ckets.jpg

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

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

4

2 回答 2

0

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 )
{

}

}

于 2013-03-04T14:14:19.613 回答
0

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

下面是一个数据包的 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 可以将其视为 ahttp并可能使用Content-Length: 280. 所以 280 字节的左边部分永远不会触发 SOCKET_DATA 事件。

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

于 2013-12-30T07:13:21.230 回答