Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Flash Приложения: AIR, Zinc и тд. (http://www.flasher.ru/forum/forumdisplay.php?f=94)
-   -   Проблема с UDP обменом между сервером и AIR приложением (http://www.flasher.ru/forum/showthread.php?t=153705)

jester88 07.04.2011 23:57

Проблема с UDP обменом между сервером и AIR приложением
 
Доброго времени суток!

У меня возникла следующая проблема. В локальной сети есть сервер, с которого через UDP передаются некоторые числовые данные. Мне необходимо эти данные принять и обработать в своем AIR приложении. Для прослушивания UDP сервера использую класс DatagramSocket, который позволяет отправлять и получать пакеты UDP.

Тут возникает пролема, которую я решить не могу. Мое приложение просто выполняется и совершенно ничего не приоисходит. Я нуб в ActionScript, и прошу совета знающих людей. Код выглядит следующим образом.

Код AS3:

package source
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.net.DatagramSocket;
        import flash.events.DatagramSocketDataEvent;
 
        public class ExampleDatagramSocket extends Sprite
        {
                private var udpSocket:DatagramSocket;
 
        public function ExampleDatagramSocket()
        {
                trace ("Constructor complete");
 
        }
        private function bind(event:Event):void
        {
                if (udpSocket.bound)
                {
                        udpSocket.close();
                        udpSocket = new DatagramSocket;
                }
                udpSocket.bind(8989, "127.0.0.1"); //Связываем сокет с указанным локальным адресом и портом.
                udpSocket.addEventListener(DatagramSocketDataEvent.DATA, readDataRecieved);
                udpSocket.receive(); //Активируем этот объект DatagramSocket, чтобы получить входящие пакеты на связанный IP-адрес и порт.
        }
        private function connect(event:Event):void
        {
                udpSocket.connect("192.1.130.190", 50000); //Подключаем сокет к указанному удаленному адресу и порту.
        }
        private function readDataRecieved(event:DatagramSocketDataEvent):void
        {
                if (udpSocket.connected)
                {
                        trace ("Recieved from" + event.srcAddress + ":" + event.srcPort + "> " +
                event.data.readUTFBytes( event.data.bytesAvailable )); //если сокет установил соединение с указанным сервером, то выводим данные, которые тот посылает
                }
                else
                {
                        trace ("Remote Server Unavailable"); // иначе выводим, что сервер недоступен
                }
        }
        }
}

Если бы указанный код хоть что-то выводил, я бы мог хоть как-то ориентироваться, но ни один трейс не работает. Помогите пожалуйста разобраться в чем дело.

alexcon314 08.04.2011 08:57

Непонятна логика работы вашенго класса. И почему биндимся на локалхост?
Разберитесь до конца с примером из хэлпа:
Код:

package
{
    import flash.display.Sprite;
    import flash.events.DatagramSocketDataEvent;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.net.DatagramSocket;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFieldType;
    import flash.utils.ByteArray;
    import flash.utils.Timer;
   
    public class DatagramSocketExample extends Sprite
    {
        private var datagramSocket:DatagramSocket = new DatagramSocket();;

        private var localIP:TextField;
        private var localPort:TextField;
        private var logField:TextField;
        private var targetIP:TextField;
        private var targetPort:TextField;
        private var message:TextField;
       
        public function DatagramSocketExample()
        {
            setupUI();
        }

        private function bind( event:Event ):void
        {
            if( datagramSocket.bound )
            {
                datagramSocket.close();
                datagramSocket = new DatagramSocket();
               
            }
            datagramSocket.bind( parseInt( localPort.text ), localIP.text );
            datagramSocket.addEventListener( DatagramSocketDataEvent.DATA, dataReceived );
            datagramSocket.receive();
            log( "Bound to: " + datagramSocket.localAddress + ":" + datagramSocket.localPort );
        }
       
        private function dataReceived( event:DatagramSocketDataEvent ):void
        {
            //Read the data from the datagram
            log("Received from " + event.srcAddress + ":" + event.srcPort + "> " +
                event.data.readUTFBytes( event.data.bytesAvailable ) );
        }
       
        private function send( event:Event ):void
        {
            //Create a message in a ByteArray
            var data:ByteArray = new ByteArray();
            data.writeUTFBytes( message.text );
           
            //Send a datagram to the target
            try
            {
                datagramSocket.send( data, 0, 0, targetIP.text, parseInt( targetPort.text ));
                log( "Sent message to " + targetIP.text + ":" + targetPort.text );
            }
            catch ( error:Error )
            {
                log( error.message );
            }
        }
       
        private function log( text:String ):void
        {
            logField.appendText( text + "\n" );
            logField.scrollV = logField.maxScrollV;
            trace( text );
        }
        private function setupUI():void
        {
            targetIP = createTextField( 10, 10, "Target IP:", "192.168.0.1" );
            targetPort = createTextField( 10, 35, "Target port:", "8989" );
            message = createTextField( 10, 60, "Message:", "Lucy can't drink milk." );
            localIP = createTextField( 10, 85, "Local IP", "0.0.0.0");
            localPort = createTextField( 10, 110, "Local port:", "0" );
            createTextButton( 250, 135, "Bind", bind );
            createTextButton( 300, 135, "Send", send );
            logField = createTextField( 10, 160, "Log:", "", false, 200 )
               
            this.stage.nativeWindow.activate();
        }
       
        private function createTextField( x:int, y:int, label:String, defaultValue:String = '', editable:Boolean = true, height:int = 20 ):TextField
        {
            var labelField:TextField = new TextField();
            labelField.text = label;
            labelField.type = TextFieldType.DYNAMIC;
            labelField.width = 180;
            labelField.x = x;
            labelField.y = y;
           
            var input:TextField = new TextField();
            input.text = defaultValue;
            input.type = TextFieldType.INPUT;
            input.border = editable;
            input.selectable = editable;
            input.width = 280;
            input.height = height;
            input.x = x + labelField.width;
            input.y = y;
           
            this.addChild( labelField );
            this.addChild( input );
           
            return input;
        }
       
        private function createTextButton( x:int, y:int, label:String, clickHandler:Function ):TextField
        {
            var button:TextField = new TextField();
            button.htmlText = "<u><b>" + label + "</b></u>";
            button.type = TextFieldType.DYNAMIC;
            button.selectable = false;
            button.width = 180;
            button.x = x;
            button.y = y;
            button.addEventListener( MouseEvent.CLICK, clickHandler );
           
            this.addChild( button );
            return button;
           
        }
    }
}


jester88 08.04.2011 11:56

Я понимаю логику работы программы так. Есть два компьютера. Один удаленный, он отсылает в сеть UDP пакеты. Второй - локальный. На локальном компьютере находится AIR приложение, которое по задумке должно принимать пакеты, обрабатывать их и выводить результаты.
Исходя из этого, программа выглядит следующим образом. Создаем объект DatagramSocket, далее подключаемся с помощью метода connect() к удаленному компьютеру (IP="192.1.130.190", Port=50000), отсылающему в сеть пакеты. Далее с помощью метода bind() связываем DatagramSocket с локальным адресом и портом (IP="127.0.0.1", PORT=8989). Я так понял, что локальный адрес - это localhost. Ставим слушатель событий, который следит за тем, приходят ли пакеты на связанный локальный адрес. Если пакеты приходят, то выполняется функция readUDPSocketData, которая по идее должна трейсить, что такие-то данные получены с такого-то адреса и порта. В конце-концов пишем recieve() для активации объекта DatagramSocket, чтобы тот смог получать пакеты на связанный IP-адрес и порт.

Я так понимаю, в моей логике где-то содержится epic fail. Укажите на него пожалуйста.

P.S. С примером их хелпа разбирался, но тот не работает, выводит ошибку #1009. Но красивости, всякие окошки и поля ввода мне сейчас неинтересны, хочется чтобы просто данные передавались.

alexcon314 08.04.2011 13:06

1. Удаленный компьютер вещает пакеты в сеть безадресно? Как организована его работа?
2. Локальный компьютер имеет свой IP-адрес? На него и надо делать бинд, ну, или просто bind(), без параметров. Бинд на локалхост означает, что будут приниматься только пакеты от локальных же приложений.
3. Пример из хелпа вполне рабочий. Более того, он позволяет проверить работу DatagramSocket, даже не имея удаленного компьютера. В этом случае как раз достаточно забиндиться на 127.0.0.1:[port] и слать пакеты на этот же адрес - 127.0.0.1:[port]. У меня под FlashDevelop пример собрался и заработал на раз-два.
4. Где в вашем примере вызываются bind() и connect() вообще не понятно. "красивости", которые вам не интересны, в примере из хелпа - это кнопки и поля ввода? Как раз события от кнопок и запускают тут bind() и connect() и позволяют потестить работу DatagramSocket. Чем они вам не угодили - не ясно.
5. Еще раз повторю: разберитесь с примером доконца.

jester88 08.04.2011 14:51

Спасибо за ответ, попытаюсь разобраться, просто под Flash Professional этот пример ни за что собираться не хочет.

ShockWave512 08.04.2011 16:18

а если не подписываться на ошибки сокета? он про них умолчит или выдаст ?

jester88 11.04.2011 20:06

Добрый день! Я разобрался в хелпе, данные сейчас передаются, но возникла очередная загвоздка. UDP сервер, находящийся по адресу 192.1.130.178:55556, отсылает в сеть пакеты на адрес 192.1.130.178:55555. В качестве UDP сервера используется стандартный блок сетевого обмена UDP пакета MATLAB&Simulink. Числовые данные, приходя в мое AIR приложение, превращаются в ничего не говорящие мне символы в виде квадратов. Выглядит это следующим образом.
Код AS3:

[SWF] recieve.swf - 2970 байт после декомпрессии
Received from 192.1.130.178:55556>
Received from 192.1.130.178:55556>
Received from 192.1.130.178:55556>
Received from 192.1.130.178:55556>
Received from 192.1.130.178:55556>
Received from 192.1.130.178:55556>
Received from 192.1.130.178:55556>
Received from 192.1.130.178:55556> символ
Received from 192.1.130.178:55556> символ
Received from 192.1.130.178:55556> символ
Received from 192.1.130.178:55556> символ
Received from 192.1.130.178:55556> символ
Received from 192.1.130.178:55556> символ
Received from 192.1.130.178:55556> символ

Я поначалу думал на сам сервер матлаба, однако потом поверил его вместе с авиасимулятором FlightGear, они друг друга прекрасно понимают. На уровне интуиции я понимаю, что проблема в кодировке. Но это только на уровне интуиции...

Код программы здесь.
Код AS3:

package source
{
import flash.display.Sprite;
import flash.events.DatagramSocketDataEvent;
import flash.events.Event;
import flash.net.DatagramSocket;
import flash.utils.ByteArray;
 
public class DatagramSocketExample extends Sprite
{
    private var datagramSocket:DatagramSocket;
 
    //The IP and port for this computer
    private var localIP:String = "192.1.130.178";
    private var localPort:int = 55555;
 
    //The IP and port for the target computer
    private var targetIP:String = "192.1.130.178";
    private var targetPort:int = 55556;
 
    public function DatagramSocketExample()
    {
        datagramSocket = new DatagramSocket();       
        datagramSocket.addEventListener( DatagramSocketDataEvent.DATA, dataReceived );
 
        //Bind the socket to the local network interface and port
        datagramSocket.bind( localPort, localIP );
 
        //Listen for incoming datagrams
        datagramSocket.receive();
    }
 
    public function dataReceived( event:DatagramSocketDataEvent ):void
    {
        //Read the data from the datagram
        trace("Received from " + event.srcAddress + ":" + event.srcPort + "> " +
            event.data.readUTFBytes(event.data.bytesAvailable));
 
    }
}
}

Укажите, пожалуйста, в чем может быть дело.

ShockWave512 11.04.2011 20:22

если попробовать Socket или XMLSocket ?
и что там за протокол у матлаба ?

jester88 11.04.2011 21:38

Матлаб имеет стандартный UDP протокол, и все числовые транзакции осуществляются именно через него, поэтому Socket и XMLSocket не подходят к сожалению...

Котяра 12.04.2011 03:50

под протоколом в данном случае подразумевается более высокий уровень. какие данные и в каком виде шлёт матлаб по UDP? скорей всего это какой-то бинарный протокол, который нужно отдельно парсить.


Часовой пояс GMT +4, время: 17:03.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.