Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 839
  • Last Modified:

Terminate telnet stream into Flex component to be used as data for eventlistners...

I am using the TelnetSocket example from Adobe to connect to a server which I am using to monitoring the events of an application. The TelenetSocket example takes the received data from the telnet feed and writes that to a text box and that is working fine.

What I need to do is take the telnet feed and terminate that into a component. The component will parse the data in return will send off events to other custom components I will build to listen to those events. Then in turn those components will modify their image and labels based on those received events.

So the question for this post is how do I terminate the telnet feed into something other than the text box?

Joel

#############TelenetSocket.mxml################
 
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="vertical">
    
    <mx:Script>
        <![CDATA[
            import com.example.programmingas3.socket.Telnet;
            private var telnetClient:Telnet;
            private function connect():void {
                telnetClient = new Telnet(serverName.text, int(portNumber.text), output);
                console.title = "Connecting to " + serverName.text + ":" + portNumber.text;
                console.enabled = true;
            }
            private function sendCommand():void {
                var ba:ByteArray = new ByteArray();
                ba.writeMultiByte(command.text + "\n", "UTF-8");
                telnetClient.writeBytesToSocket(ba);
                command.text = "";
            }
        ]]>
    </mx:Script>
    
    <mx:Label id="title" text="Telnet Socket Example" fontSize="24" fontStyle="bold" />
    <mx:Label id="subtitle" text="From Programming ActionScript 3.0, Chapter 22: Networking and communication" fontSize="12" />
 
    <mx:ApplicationControlBar width="100%">
        <mx:Label text="Server:" />
        <mx:TextInput id="serverName" width="100%" />
        <mx:Spacer />
        <mx:Label text="Port:" />
        <mx:TextInput id="portNumber" text="23" textAlign="right" maxChars="5" restrict="0-9" />
        <mx:Spacer />
        <mx:Button label="Login" click="connect();" />
    </mx:ApplicationControlBar>
 
    <mx:Spacer />
 
    <mx:Panel id="console" enabled="false" width="100%" height="100%" paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
        <mx:TextArea id="output" editable="false" width="100%" height="100%" fontFamily="Courier New" />
        <mx:ControlBar>
            <mx:Label text="Command:" />
            <mx:TextInput id="command" width="100%" enter="sendCommand();" />
            <mx:Button label="Send" click="sendCommand();" />
        </mx:ControlBar>
    </mx:Panel>
 
</mx:Application>
 
 
 
################Telnet.as file###############
package com.example.programmingas3.socket {
    import flash.events.*;
    import flash.net.Socket;
    import flash.system.Security;
    import flash.utils.ByteArray;
    import flash.utils.setTimeout;
    
    import mx.controls.TextArea;
    import mx.core.UIComponent;
 
    public class Telnet extends UIComponent{
        private const CR:int = 13; // Carriage Return (CR)
        private const WILL:int = 0xFB; // 251 - WILL (option code)
        private const WONT:int = 0xFC; // 252 - WON'T (option code)
        private const DO:int   = 0xFD; // 253 - DO (option code)
        private const DONT:int = 0xFE; // 254 - DON'T (option code)
        private const IAC:int  = 0xFF; // 255 - Interpret as Command (IAC)
 
        private var serverURL:String;
        private var portNumber:int;
        private var socket:Socket;
        private var ta:TextArea;
        private var state:int = 0;
        
        public function Telnet(server:String, port:int, output:TextArea) {
            // set class variables to the values passed to the constructor.
            serverURL = server;
            portNumber = port;
            ta = output;
            
            // Create a new Socket object and assign event listeners.
            socket = new Socket();
            socket.addEventListener(Event.CONNECT, connectHandler);
            socket.addEventListener(Event.CLOSE, closeHandler);
            socket.addEventListener(ErrorEvent.ERROR, errorHandler);
            socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            socket.addEventListener(ProgressEvent.SOCKET_DATA, dataHandler);
            
            // Load policy file from remote server.
            Security.loadPolicyFile("http://" + serverURL + "/crossdomain.xml");
            // Attempt to connect to remote socket server.
            try {
                msg("Trying to connect to " + serverURL + ":" + portNumber + "\n");
                socket.connect(serverURL, portNumber);
            } catch (error:Error) {
                /*
                    Unable to connect to remote server, display error 
                    message and close connection.
                */
                msg(error.message + "\n");
                socket.close();
            }
        }
        
        /**
         * This method is called if the socket encounters an ioError event.
         */
        public function ioErrorHandler(event:IOErrorEvent):void {
            msg("Unable to connect: socket error.\n");
        }
        
        /**
         * This method is called by our application and is used to send data
         * to the server.
         */
        public function writeBytesToSocket(ba:ByteArray):void {
            socket.writeBytes(ba);
            socket.flush();
        }
        
        private function connectHandler(event:Event):void {
            if (socket.connected) {
                msg("connected...\n");
            } else {
                msg("unable to connect\n");
            }
        }
        
        /**
         * This method is called when the socket connection is closed by 
         * the server.
         */
        private function closeHandler(event:Event):void {
            msg("closed...\n");
        }
        
        /**
         * This method is called if the socket throws an error.
         */
        private function errorHandler(event:ErrorEvent):void {
            msg(event.text + "\n");
        }
        
        /**
         * This method is called when the socket receives data from the server.
         */
        private function dataHandler(event:ProgressEvent):void {
            var n:int = socket.bytesAvailable;
            // Loop through each available byte returned from the socket connection.
            while (--n >= 0) {
                // Read next available byte.
                var b:int = socket.readUnsignedByte();
                switch (state) {
                    case 0:
                        // If the current byte is the "Interpret as Command" code, set the state to 1.
                        if (b == IAC) {
                            state = 1;
                        // Else, if the byte is not a carriage return, display the character using the msg() method.
                        } else if (b != CR) {
                            msg(String.fromCharCode(b));
                        }
                        break;
                    case 1:
                        // If the current byte is the "DO" code, set the state to 2.
                        if (b == DO) {
                            state = 2;
                        } else {
                            state = 0;
                        }
                        break;
                    // Blindly reject the option.
                    case 2:
                        /*
                            Write the "Interpret as Command" code, "WONT" code, 
                            and current byte to the socket and send the contents 
                            to the server by calling the flush() method.
                        */
                        socket.writeByte(IAC);
                        socket.writeByte(WONT);
                        socket.writeByte(b);
                        socket.flush();
                        state = 0;
                        break;
                }
            }
        }
        
        /**
         * Append message to the TextArea component on the display list.
         * After appending text, call the setScroll() method which controls
         * the scrolling of the TextArea.
         */
        private function msg(value:String):void {
            ta.text += value;
            ta.dispatchEvent(new Event(Event.CHANGE));
            setTimeout(setScroll, 100);
        }
 
        /**
         * Scroll the TextArea component to its maximum vertical scroll 
         * position so that the TextArea always shows the last line returned
         * from the server.
         */
        public function setScroll():void {
            ta.verticalScrollPosition = ta.maxVerticalScrollPosition;
        }
    }
}

Open in new window

0
Joel_Sisko
Asked:
Joel_Sisko
  • 8
  • 6
1 Solution
 
evcrCommented:
That would depend on what the feed looks like. Can you post an example?
0
 
Joel_SiskoAuthor Commented:
Kinda simple format but nothing consistent and events will change as new features are added to application we are monitoring.

Joel


##############Begin Telnet Stream#############
 
Event: Newstate
Privilege: none
User: Jim
State: Working
UserID: 99901111
Application: CRM
Uniqueid: 1226775852.7348
 
Event: Up
Privilege: system
User: Jim
State: Available
UserID: 99901111
Application: CRM 
Uniqueid: 1226775852.7348
 
Event: Newstate
Privilege: none
User: Jim
State: Working
UserID: 99901111
Application: Email
Uniqueid: 1226775852.7349
 
Event: Up
Privilege: Public
User: System
State: Up

Open in new window

0
 
evcrCommented:
Assuming that is a rolling output and it's added to at the top you probably only want the topmost block of data.

You can split that output in an array e.g.

outputArray = yourText.split(char(13)char(13)); //split the whole output into blocks of data
topmostArray = outputArray[0].split(char(13)); //get the topmost block of data and split by line

tmpArray = new Array;

for (var i:int;i<topmostArray.length();i++) {
    tmpArray= topmostArray[i].split(': ');
    trace(tmpArray(tmpArray[0])); //output the 1st element e.g. 'Event'
    trace(tmpArray(tmpArray[1])); //output the 2nd element e.g. 'Newstate''
//Do what you need to with the result...
}

Completely untested & unlikely to work striaght off but it should put you on the right track!
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
Joel_SiskoAuthor Commented:
Thanks for the help. Will give it a go. Just a follow up regarding this, how does the system know that it is the end of the block of data? Is there a way to set it so that when "Event" is first recognized that all data following is part of that block until next "Event" is received?, which should be a new block of data?

Joel
0
 
evcrCommented:
Yeah after posting that I thought I may have sold you a bit short there :-)

It depends how the feed works.

I'll see if I can set up a quick test environment for this as to be honest I've never used that component before.


0
 
Joel_SiskoAuthor Commented:
Thanks.

Joel
0
 
Joel_SiskoAuthor Commented:
evcr,

Found this while researching arrays:

http://www.adobe.com/devnet/flex/quickstart/using_data_providers/#collections_mxml

Looks like using the ArrayCollection class will be the way to go. The bottom code looks like it has the base code for what I am looking to do (kinda).


Joel
0
 
evcrCommented:
ok, i've got that set up.

one question, are you running a remote process that provides the feed or are you tapping into an already running remote process to get it's feed?

0
 
evcrCommented:
yes further down the line it's a good idea to use an arraycollection but you first need to disseminate the raw output. You need to get that data into an array and use the telnet events in order for it to update the collection.

Do you need any more help?
0
 
Joel_SiskoAuthor Commented:
Definitely will need help, but let me hack at his a bit the next day or two (also learning as I go along).

If anything how do I debug or use "trace" so I can monitor as the application runs the code I compile?

Joel
0
 
evcrCommented:

Trace:
 trace(somethingToTrace); //in your code
Then use the console output panel in Flex Builder to see what's returned.
You can also see object results by using the Objectutils package e.g.

import mx.utils.ObjectUtil;
....
trace(ObjectUtil.toString(objectToTrace));

Debugging:
1. Highlight a variable in your code and right click Watch "yourVarHere"
2. On the next line or so right click on the margin of the code window and choose 'Toggle Breakpoint'
3. Open the Watch panel in flex and press F11 to run the program in debug mode.

Pretty easy when you get used to it.

0
 
evcrCommented:
more debugging:

At a breakpoint press the green play button to continue running the code or stop it using the red stop button
right click on the blue breakpoint marker to turn off the breakpoint.

That's the basics I think.

0
 
Joel_SiskoAuthor Commented:
Thanks.
0
 
evcrCommented:
Thanks for accepting that solution, I'll keep an eye out for any more on this subject
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 8
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now