Copy link to clipboard
Copied
I have an issue with a college project I'm working on.
Using Actionscript 3, I made a simple .swf program, an animated, interactive smiley, that 'reacts' to number inputs in a input-box.
For the sake of the project, I now need to make the framework for establishing a socket connection with the smiley .swf, and another program.
This is where I encounter issues. I have very little knowledge of AS3 programming, so I'm not certain how to establish the connection - what's required code-wise for it, that is.
To test the connection, I'm attempting to use the "TCP/IP builder" program from windows, which lets me set up a server socket. I need to program the .swf file into a client - to recognize it, connect to it, then be able to receive data (so that the data can then be used to have the smiley 'react' to it - like how it does now with the input-box, only 'automatically' as it gets the data rather than by manual input).
My attempts at coding it are as follows, using a tutorial (linked HERE😞
//SOCKET STUFF GOES HERE
//****************************************************************
var socket:XMLSocket;
stage.addEventListener(MouseEvent.CLICK, doConnect);
// This one connects to local, port 9001, and applies event listeners
function doConnect(evt:MouseEvent):void
{
stage.removeEventListener(MouseEvent.CLICK, doConnect);
socket = new XMLSocket("127.0.0.1", 9001);
socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
}
// This traces the connection (lets us see it happened, or failed)
function onConnect(evt:Event):void
{
trace("Connected");
socket.removeEventListener(Event.CONNECT, onConnect);
socket.removeEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(DataEvent.DATA, onDataReceived);
socket.addEventListener(Event.CLOSE, onSocketClose);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUp);
}
function onError(evt:IOErrorEvent):void
{
trace("Connect failed");
socket.removeEventListener(Event.CONNECT, onConnect);
socket.removeEventListener(IOErrorEvent.IO_ERROR, onError);
stage.addEventListener(MouseEvent.CLICK, doConnect);
}
// Here, the flash tracks what keyboard button is pressed.
// If 'q' is pressed, the connection ends.
function keyUp(evt:KeyboardEvent):void
{
if (evt.keyCode == 81) // the key code for q is 81
{
socket.send("exit");
}
else
{
socket.send(evt.keyCode);
}
}
// This one should handle the data we get from the server.
function onDataReceived(evt:DataEvent):void
{
try {
trace("From Server:", evt.data );
}
catch (e:Error) {
trace('error');
}
}
function onSocketClose(evt:Event):void
{
trace("Connection Closed");
stage.removeEventListener(KeyboardEvent.KEY_UP, keyUp);
socket.removeEventListener(Event.CLOSE, onSocketClose);
socket.removeEventListener(DataEvent.DATA, onDataReceived);
Trying to connect to the socket gives me either no result (other than a 'connection failed' message when I click the .swf), or the following error:
at Smiley_TCP_IP_v4_fla::MainTimeline/doConnect()[Smiley_TCP_IP_v4_fla.MainTimeline::frame1:12]
1 Correct answer
127.0.0.1 might be taken over via your HTTP software, I'm not familiar with the tool you're using. It also might have been repointed in your hosts file (in Windows you'll find that here: C:\Windows\System32\drivers\etc). Check to see if anything is overriding 127.0.0.1 (local loopback).
Outside that, I gave you source to a quick AIR server that just opens a listener at 127.0.0.1:8910 so you'd need no other tools to test the client, even though you have one. I just include the source and a produce
...Copy link to clipboard
Copied
You're on the right path with the essential way you think you need to set it up, but you're using the wrong class. Class names are pretty self descriptive in AS3. You're using an XMLSocket when you can simply use a basic Socket:
Socket - Adobe ActionScript® 3 (AS3 ) API Reference
You'd use it the same way you use XMLSocket, although it does require sending a request to receive a response from the server (unlike XMLSocket).
Follow the same process. Make a new Socket, connect to the host/port, then send any requests you want which will be received by the TCP/IP app you made. Anything sent back comes to the socketData event. Read the data using the method that matches the data type and do with it what you wish.
Copy link to clipboard
Copied
I tried fiddling around with those earlier, but I kept running into issues (most likely me doing something wrong out of lack of any experience). Classes wise, I've been having trouble getting most of those Adobe guide "examples" and constructor (which all those tutorials ask but don't really clarify) to work.
I've no idea what the procedure/steps for the 'constructor' to make said socket is, or what it is in relation to the .swf - is it it's own file/batch of code that has to be in same folder as the .swf, or can it be made as part of the .swf? How do I initiate/use the 'constructor' to make it, in AS3/Flash Professional?
Do I actually need to use class/package tags, for my example, if I code it directly into the .swf?
Cause, whenever I tried to put the adobe "example" packages in a layer/frame of the .swf (the method I used to program the .swf so far), I keep getting errors that require me to delete most of the class and package descriptors/brackets (first some vague bracket error, can't remember what anymore, that only goes away if I get rid of the 'package' part, then successive errors that insist 'class' & other related code stuff is only for packages...), and then it still doesn't work anyway. I assume I can't use classes in the .swf layers itself?
Note: For reference, most of the smiley I've constructed/coded, and the AS3 code stuff I know so far, has been done referencing this video, plus some basic knowledge/code of how input boxes work. Most of my code is in 'layers' like the video does. How would the socket need it coded? Externally, or within the .swf?
Copy link to clipboard
Copied
First to clear up using Flash and code together, there's 2 most common ways.
1) Writing code directly in a frame on the timeline is a "frame script". That's when you click in any frame, open the actions panel and start writing code in there. You do not specify classes and packages here because you are already inside one.
2) Writing code in external files with an .as file extension is the other way. You point your Flash projects ActionScript source path at the folder your code exists in (or you don't need to do that if the FLA and .as files are in the same folder). The AS3 code in that external .as file must be wrapped in a package and class. You can then import it into your FLA to use it.
The choice is yours on which method suits you best.
That said, if you are trying to communicate with a port below 1024 or cross domains, in FP v9.0.115.0 and above, the SWF expects a socket policy file to be sent when establishing a connection. This is explained in the relevant Socket class documentation. If you're not on the same domain or attempting a port below 1024 then this is a good reason any connection will fail. Flash is heavily sandboxed for security.
For the sake of simplicity, lets assume you have a server accepting TCP connections on port 8910 and you're running code from inside a frame script (no package or class needed). You could connect to it as simple as clicking in a frame and typing:
var sock:Socket = new Socket('127.0.0.1',8910);
Of course you'll want to pay attention to security errors, IO errors, connections, connection loss and actual data coming in. It's a bit too much to type here so I'll rip some simple AIR server code and make an AIR server listening on that local port that will just print text to the screen or echo back any strings written to it. Along with that a simple client example connecting to the server, receiving a connect string, sending back another string and receiving it back in echo. Saved down to CS5
Example Simple Socket Connect:
http://www.ertp.com/tmp/SocketExample.zip
You can just open the client and point it toward your HTTP app as well but the communication methods are very simple in Flash, as long as you know the sandbox limits. I included an example of that, trying to connect to google.com:21 (security error). Hope it helps you understand the simple socket class. Do keep in mind I should be removing listeners, etc etc but I know you know that from your code so I didn't bother.
Copy link to clipboard
Copied
Thanks for the help so far! I modified the code of my stuff into the following:
//SOCKET STUFF GOES HERE
//****************************************************************
// Just import stuff
import flash.net.Socket;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.ProgressEvent;
var sock:Socket = new Socket();
sock.addEventListener(Event.CONNECT, onConnect);
sock.addEventListener(Event.CLOSE, onClose);
sock.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
sock.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecErr);
sock.addEventListener(IOErrorEvent.IO_ERROR, onIOErr);
// Connect!
sock.connect('127.0.0.1',8910);
// play with bad connects
//sock.connect('127.0.0.1',21); // IOErrorEvent Error #2031: Socket Error. URL: 127.0.0.1
//sock.connect('192.168.1.1',80); // connected! (usually your routers HTTP admin)
//sock.connect('google.com',21); // SecurityErrorEvent Error #2048: Security sandbox violation
/////////////////////////////////////////////////////////////////////////////
// Receive data from socket...
function onSocketData(e:ProgressEvent):void
{
trace(sock.bytesAvailable + ' byte(s) available');
// Read the socket data...
if (sock.bytesAvailable > 0)
{
// String...
var msg:String = sock.readUTFBytes(sock.bytesAvailable);
trace(msg);
if (msg == 'Connected.')
{
// Send a message back to the server (which it will return confirm if it worked).
sock.writeUTFBytes('Thanks for connecting!');
}
// Flush!
sock.flush();
}
}
// Connect socket...
function onConnect(e:Event):void
{
trace('Connected! ' + e);
}
// Close socket...
function onClose(e:Event):void
{
// Clean up...
sock.flush();
sock.close();
sock = null;
}
// Error events...
function onSecErr(e:SecurityErrorEvent) { trace('SecurityErrorEvent: ' + e); }
function onIOErr(e:IOErrorEvent) { trace('IOErrorEvent: ' + e); }
function onError(evt:IOErrorEvent):void
{
trace("Connect failed");
sock.removeEventListener(Event.CONNECT, onConnect);
sock.removeEventListener(IOErrorEvent.IO_ERROR, onError);
}
function onDataReceived(evt:DataEvent):void
{
try {
trace("From Server:", evt.data );
}
catch (e:Error) {
trace('error');
}
}
function onSocketClose(evt:Event):void
{
trace("Connection Closed");
sock.removeEventListener(Event.CLOSE, onSocketClose);
}
Now, when I run the .swf, I get the following message, occurring every few seconds:
IOErrorEvent: [IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2031: Socket Error. URL: 127.0.0.1"]
I also get this message again, seemingly randomly (possibly when I try to connect to the test app):
SecurityErrorEvent: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048: Security sandbox violation: file:///C|/Users/Marko/Desktop/Završni/Flash%20documents/Smiley%5FTCP%5FIP%5Fv4.swf cannot load data from 127.0.0.1:8910."]
Overall, still having issues with connecting, for some reason.
The TCP/IP builder's .exe and other relevant files are in a different folder than a .swf, but have been set to the same IP (127.0.0.1) and port (8910) as in the example.
What's going on? Security sandbox issue, or something else?
Edit: I tried to test-run the client/server files from .zip, but they don't seem to show or do anything.
Copy link to clipboard
Copied
127.0.0.1 might be taken over via your HTTP software, I'm not familiar with the tool you're using. It also might have been repointed in your hosts file (in Windows you'll find that here: C:\Windows\System32\drivers\etc). Check to see if anything is overriding 127.0.0.1 (local loopback).
Outside that, I gave you source to a quick AIR server that just opens a listener at 127.0.0.1:8910 so you'd need no other tools to test the client, even though you have one. I just include the source and a produced AIR installer so you can reproduce it to see I'm not doing anything malicious. The Server.air file should be "installed" to test it. When you double click it, it's an installer. It installs to C:\Program Files (x86)\Server (should have named it something less common hindsight). It also has a checkbox to run it after install. If you do you'll see the server pop up a standard 550x400 window with a textbox inside it letting you know it's listening. Any connects, messages (strings) and disconnects will be displayed in the server text box.
The client is the only SWF you should run, after you have "something" listening on the IP and port you configure it with.
Here's a picture showing you the server is not running from the same folder the SWF is, what the server says and what just running the client exactly how I have it should look like all together:
I'm showing you that after the Server.air installer runs, here's the the file path the executable runs from and the client SWF isn't in there. No issues connecting despite being in different locations.
The server runs and states it's listening on 8910. Feel free to edit the source and reproduce for a different IP/port.
- I open the Client.FLA and just run it. It creates a new socket, adds listeners, connects to 127.0.0.1:8910.
- The server responds that it sees and accepts the client connection. The server sends a message 'Connected.' (10 bytes) to the client right away.
- The client receives the data (string) and traces it. The client sniffs for that specific message and then sends the server a string "Thanks for connecting!".
- The server receives it and is only coded to echo the string back "Echo -- Thanks for connecting!" to verify the string is correct.
- The client receives the servers echo (30 bytes) and traces it.
Copy link to clipboard
Copied
Tried running it. The server shows as listening, but doesn't respond to the client (and the client doesn't show anything) when run via flash player or firefox. And when I tried to connect to the server via the TCP/IP builder (it can either connect-to or listen-to), it stated that the address was either already occupied (when trying to make a listening socket of the same address), or that the connection was rejected (when trying to connect to it).
I think I'm having an issue with the address/ports themselves...
Checking 'hosts' and 'networks' file, I got the following in them:
Hosts
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
Networks
# Copyright (c) 1993-1999 Microsoft Corp.
#
# This file contains network name/network number mappings for
# local networks. Network numbers are recognized in dotted decimal form.
#
# Format:
#
# <network name> <network number> [aliases...] [#<comment>]
#
# For example:
#
# loopback 127
# campus 284.122.107
# london 284.122.108
loopback 127
How can I check for potential conflicts? Is there some other address/port combo I can try as an alternative?
Copy link to clipboard
Copied
Ping 127.0.0.1
Copy link to clipboard
Copied
Well, pinging shows 127.0.0.1 as working (0 packets lost)...
Now I'm confused. Or doing something terribly wrong. Maybe I need the security file/commands...
Is the code I have so far actually functional (for a super-basic connection at the very least)? In case it's just my laptop being wonky?
Copy link to clipboard
Copied
You still have some legacy code in there you don't need like function onDataReceived from your old code but it shouldn't stop this code from running. I'd rather you work with my simple client example and just get that working first, because I know it works and it's as simple as you can get.
Just to get around whatever is messing with your localhost and use your real local IP. I'm sure you know how to get it but if not the fastest way is start->run, type 'cmd' and click OK (or hit enter), then type 'ipconfig' and look for machines LAN IP address. Use that IP instead of 127 and see if it makes a difference.
Copy link to clipboard
Copied
Alright, I think I found an alternate IP...
How do I edit your server's IP, though, after I've already installed it, so I can check if it works?
If I want to test out your server/client on another machine/PC, do I need anything besides a flash player / browser?
Copy link to clipboard
Copied
You uninstall it like any other program you install (control panel->programs and features->select 'Server' by UNKNOWN publisher->uninstall).
After that I'm pretty sure you can use whatever version of AIR you have but the code that tells the server what IP and port to listen on is on line 50. You set your project to export AIR for Desktop. You can edit the XML file and change the <name> of the app if the generic 'Server' app name conflicts. Then just publish the app after you adjusted the IP and port.
Maybe a screenshot will help (again your version of AIR may differ but if it's extremely old you should consider downloading the latest AIR and adding that SDK in Help->Manage Adobe AIR SDK...):
You can generate your own certificate to export or use the included throw-away .p12 I included (I believe the password is 'socket').
After you export you'll have an .air file. Run it, let it install and your changes will be in effect when you run it.
Copy link to clipboard
Copied
Tested the thing on another PC, it worked!
Seems that there is indeed something with my laptop that's blocking the heck out of the socket connection. Same thing seems to happen with other stuff, too, downloading Blizzard's "Battle net" client, for example, doesn't work for some net-related reason... What can cause an outright socket connection block with no clear cause? Firewalls (Malwarebytes, Windows7 firewall)?
Now that I've got the connection 'working', how do I proceed? What kind of code/framework is required to receive, then direct data, into a 'input box'?
If I've set said input box to only allow numerical inputs (numbers from 0-9, and up to three digits), would data received from sockets still be able to 'go through' without any hitches (e.g. you send text letters and they bypass the restrictions, or potentially cause errors due to the code trying to shoehorn it whilst being unable to do so)?
Code wise, I've set it up like this:
// Prevents non-numbers from being entered into the text box.
unosbox.restrict = "0123456789";
// Tracks the text in the input box only when enter is pressed.
unosbox.addEventListener(KeyboardEvent.KEY_DOWN,handler);
function handler(event:KeyboardEvent){
// Checks if the key used is 'ENTER'.
if(event.charCode == 13){
// Converts the text from the input box into the output box.
outputbox1.text = unosbox.text;
// Turns the value from input box into a number.
var code:Number = Number(unosbox.text);
(unosbox = input box)
The 'Number' is then manipulated into digits and alters the smiley. I need to have the 'number' be inputted via a socket-connection-sent data, automatically (that is, without mouse/keyboard prompts on the client itself). Some method of tracking or displaying the data received would also help.
Copy link to clipboard
Copied
When you install apps like fiddler that are designer to intercept TCP/IP traffic (like the Microsoft tool you installed perhaps?) they put themselves in the network stack so they can properly view and alter the packets coming and going. I'd uninstall anything like that and even temporarily disable Windows Firewall (and any other firewalls) just to see if you can get through.
After that, anything you receive over the socket should simply be validated. If you expect numbers but get letters, you'll need to handle that situation yourself. If you get what you expect, then also proceed accordingly.
A good tool to always use is try {} catch() {}. If you expect something to work but it doesn't, the catch fires off, giving you a chance to handle the situation without throwing an exception that halts your program.
e.g.
function onSocketData(e:ProgressEvent):void
{
// Read the socket data...
if (sock.bytesAvailable > 0)
{
try
{
// Number (non-floating point)
var msg:int = sock.readInt(sock.bytesAvailable);
// validate
if (msg == 123)
{
// do stuff
}
}
catch (e:Error)
{
// some error occured, handle it here
}
sock.flush();
}
}
Frameworks are probably overkill for you but I don't ultimately know what you're doing. I think your handler should do its job trying to receive the data, validate it and if it's correct, send that data to another function to actually utilize it. No framework needed.
Copy link to clipboard
Copied
Alas, Sinious, I seem to be having more issues with my program. Sorry if this is bothering or pestering you...
First off, to simplify things, here are links to my animation/smiley for download. Should let one get a better look at it.
https://www.dropbox.com/s/eu75kzn5lgd32fq/Smiley_TCP_IP_v4.fla?dl=0
https://www.dropbox.com/s/qbu5lxtg510nq18/Smiley_TCP_IP_v4.swf?dl=0
The code used for the socket is the old one.
First off, when I run my .swf, I get the following error spammed, every few seconds:
IOErrorEvent: [IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2031: Socket Error. URL: 127.0.0.1"]
I assume this is cause it's trying to connect every now and then, and failing on account of no socket being present.
Next, I use the "TCP/IP builder" program (this one), to create a socket on IP 127.0.0.1 and port 8910. I set the thing to listen. Almost immediately, I get a notification the the connection happened for the TCP/IP builder (not the one that the .swf is supposed to send), and I get the following message in my flash client:
Connected! [Event type="connect" bubbles=false cancelable=false eventPhase=2]
So, the connection works. Using the TCP/IP builder, I can send text messages. I do so immediately after I connect. For example, I type in "Here's some information." and send it.
I get the following in the flash client:
23 byte(s) available
Here's some information
So, it seems it indeed connects, and can receive/track messages I send via the TCP/IP builder.
I also try sending "Connected.", which I assume should reply with "Thanks for Connecting!", but it doesn't do that. Probably lacking code to do so, or the TCP/IP builder isn't recognizing it properly to 'get' its messages.
Now, things get strange past this point.
After a few seconds pass since the connection was initiated, I once again start getting the #2031 error spammed every few seconds.
If I try to 'send' anything with the TCP/IP builder AFTER this happens, I get the following error:
Error: Error #2002: Operation attempted on invalid socket.
at flash.net::Socket/get bytesAvailable()
at Smiley_TCP_IP_v4_fla::MainTimeline/onSocketData()[Smiley_TCP_IP_v4_fla.MainTimeline::frame1:34]
(The file is called "Smiley_TCP_IP_v4.fla")
Additionally, after about 10-30 seconds, I get this error, which starts repeating along with the #2031 error:
SecurityErrorEvent: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048: Security sandbox violation: file:///E|/Marko%20Zavrsni/Završni/Flash%20documents/Smiley%5FTCP%5FIP%5Fv4.swf cannot load data from 127.0.0.1:8910."]
So to summarize: I can connect to my program, but the connection seems to last only a few seconds before errors start happening again and the connection seemingly ends or bugs into uselessness. I have to manually restart the connection (destroy socket, re-create socket, then re-listen) for it to work properly after that point, which lasts for a few seconds before it repeats the bugs. The connection also seems to skip the other socket-relevant messages (disconnected, etc).
I think the error might be linked to my animation itself - it has about a run-time of 4 seconds before it 'loops back' to its start. Does the connection 'reset' along with it? How do I fix this?
Here's a picture of the frames for reference.
(Translation - Unesite kod = Input code; Uneseno = Inputted; Stotinjka = 100th digit; Desetka = 10th digit; Jedinica = singular digit)
Copy link to clipboard
Copied
I don't have that tool and with the communication issues it gave your local port I hesitate to install it .
Did you ever open the server code and edit the IP/Port and work with that? You can always add inputs/buttons on the screen so you can enter characters to send back to any connected clients. I'd be interested if the socket connection drops to the AIR server.
What I'm trying to do is weed out if your TCP/IP app is the culprit here or if there's something misconfigured in Flash. The socket shouldn't drop but there may be a preference you didn't check for that will timeout a socket in the TCP/IP app if no data is being sent after X seconds. You should look for that as it would explain some of what's going on.
Before reconnecting you should be disposing the socket before using it again. You should run flush() on it and close() before attempting a reconnect.
So let's ditch the TCP/IP app just for now and see if the AIR server is giving you the same issues. After you get a successful connect on the server side you can see I send back a message immediately. Just use a timed event and send that message some number of seconds later. Use a long enough delay so you're sure your TCP/IP app would have failed before that point. 5 minutes even. You can use setTimeout to call it a single time or use the Timer or setInterval class to repeatedly call a function every [X delay].
e.g.
import flash.utils.Timer;
import flash.events.TimerEvent;
// ...
var sock:Socket = new Socket()
// ....inside socket connected handler
var timer1:Timer = new Timer(300000, 0);
timer1.addEventListener(TimerEvent.TIMER, handleTimer);
timer1.start();
// .. every 5 minutes write this to the socket
function handleTimer(e:TimerEvent):void
{
serverSocket.writeUTFBytes("Some message here after 5 minutes");
serverSocket.flush();
}
Set the timer up with the milliseconds that makes sense and repeat the message. See if you can get the SWF and AIR server to break connection.
Copy link to clipboard
Copied
I'm having trouble editing the AIR server.
So far, I added the timer into the server.fla file, as well as a button that allows text input, which gets traced (to use to send data with later). I then saved it as "server2.fla" (and gotten a matching xml. file).
Now I can't figure out how to export the stuff as a AIR package (only offers image/selection/movie to export for the server).
File I edited is here (has a button layer, and the timer code in the socket code layer): https://www.dropbox.com/s/big6n9otx37ktl1/Server2.fla?dl=0
On the subject of the AIR server - when I run my Smiley flash, it connects to the server, and repeats:
Sending connect message
Received: Thanks for connecting!
Sending: Echo -- Thanks for connecting!
...every few seconds. In the client's compiler, I get:
Connected! [Event type="connect" bubbles=false cancelable=false eventPhase=2]
10 byte(s) available
Connected.
30 byte(s) available
Echo -- Thanks for connecting!
...repeated/spammed in the same way, every few seconds. The connection works, but it seems to keep resetting/connecting infinitely.
Copy link to clipboard
Copied
Sorry for the late replies, I usually only do so at work.
To export for AIR you choose AIR as your target using the same publish settings dropdown where you choose which version of Flash you want to target. One of the targets will be AIR for Desktop and it will say the versions of AIR it has installed. It's that easy. When you hit publish you will get an .air file.
On the reconnecting, did you start a timer that creates the connection? The timer class lets you specify the number of times the timer should fire. If you set it to 0, it means infinitely. e.g. var timer1:Timer = new Timer(1000, 0); would make a timer that fires every 1000 milliseconds forever. If you just wanted it to run once it'd look like: var timer1:Timer = new Timer(1000, 1); where the second argument controls the number of times it's firing. So are you letting a timer run forever making the connection?
And yes that output is what I screenshotted above so it's working correct. What I don't see is any trace of a socket close() so the connection is not closing itself. It's being reinitiated over and over, but it's not closing, so that's good. You just have to figure out why the code to connect keeps firing off and only ask it to connect once. Then after some duration, send data through the socket to verify it still exists. If it does, you know your socket disconnecting issue isn't with Flash/AIR. It's probably with the TCP/IP app you're using.
Copy link to clipboard
Copied
Published it properly (apparently I mistook the 'ok' button for the 'publish' one). Now I've got a server with a text box, that doesn't do anything just yet.
Do I have to re-publish and re-install the thing every time I want to edit and test it again?
I've set the timer to fire off once, but the connection still keeps restarting/spamming itself.
At one point in the log of the server, it spammed 'connection closed' for a while, then it once again started furiously connecting again. The client's log didn't show any sign of this (it kept showing the successful connect message the whole time).
The five-minute message didn't seem to fire off either (unless I just missed it in the wall of text, or it was in the server's flash compiler, which I can't really test properly - I cant test-run two things at once on flash professional, and running the client on firefox doesn't give a response from the server).
Copy link to clipboard
Copied
Yes, after you compile to AIR you must uninstall the old server (control panel, mentioned above) and then reinstall the new version you publish. It's a hassle but that brings the next points.
Right, you can't have two FLAs running at the same time in a single instance of Flash Pro. Hence why I made the server run stand-alone. But what you can do is use 2 instances of Flash and run it side by side. For example, here's CC 2014 and CS6 running side by side. CC 2014 is running the AIR debugger, CS6 is running the client.
Here we can see I added a 5 minute timer to fire off once. You see no disconnects or any rogue messages. After 5 minutes, the message pops up on both properly.
I used the same source files I gave you above and only added the code you see in this screenshot:
Copy link to clipboard
Copied
Adding the timer stuff to both the client and server, the following happened (don't have 2 differing versions to test with that):
1) At the 5 minute mark, the server's screen started showing the '5 minutes have elapsed'. Which it then proceeded to repeat from that point onwards, well after the 5 minute mark, along with the 'connected' message.
2) The client compiler didn't display a response of any kind to the 5 - minute message.
3) When I closed the .swf, I got instantly spammed by a dozen of 'connection closed' messages on the server, then it continued repeatedly showing the '5 minutes have elapsed' message.
Something is causing the client or server to repeatedly reset, or make infinite copies of its run-cycle.
I think I'll try to see if I can get the 'send' button to send messages to the client, since that's my goal for now.
Is it possible to convert the input box's contents directly into the 'msg' (I assume this is a universal/set variable for sent socket data, or is it a custom one?) format (aka once inputted and 'send' is pressed, it becomes 'msg' and is sent to client), then have the 'msg' be directly converted into an integer (the sent 'msg' is directly inputted into the client's input box, which then affects the animation accordingly, assuming it's a number)? Or would that create a conflict with other 'msg'-using commands?
And another oddity I've noticed: When I run the client .swf on Firefox, the 'enter' key doesn't seem to be responsive for the animation (I assume this to be a bug with the keyboard keys?). That and the previously mentioned fact it doesn't connect if ran on firefox - is that because of the local IP / port settings?
Copy link to clipboard
Copied
You certainly have different results in all sorts of ways. Here's a shot in the dark. Do you have more than 1 frame on your timeline? If so, are you running the stop() command so the timeline head isn't running over code frames, re-running the code on each frame over and over? That would definitely cause this type of behavior.
There are so many mishaps going on here that you really need to focus on just one at a time. Sometimes fixing a single issue (like not stop()ing a timeline) will fix all other issues.
If you don't know, by nature, Flash must be activated (mouse click usually) before it will receive keyboard input in a browser. Are you clicking Flash so it can receive keyboard input?
At this point I really think posting all your code on pastebin.com (or any service you like) so all of it can be seen formatted nicely would be the most advisable. There's too many things going wrong here. The examples I gave you are both 1-frame documents you should use as a barebones starting point. If they work exactly as I made them, you have no issues. If not, that's another bridge to cross.
Redownload the FLAs if you've made changes to them. So just change the IP on the Server.FLA (and port if you like), publish the server, install it (uninstalling any other previously installed) and then run it. Then open the Client.FLA, adjust the IP and port as needed, and run it in Flash debug. See if you get a successful connect. After that, per the screenshot above, add in the timer code that I added. Republish the server (uninstall/install), re-run the client and verify your socket stays open for 5 minutes. We'll go from there.
Copy link to clipboard
Copied
Yeah, I believe I do have the stop() command in there somewhere (for the animation, I think, and possibly in the code frame), and have several frames in some place (check one of the earlier pictures, and the code from files I linked via dropbox). I can do better than paste the code, I can send the whole file via dropbox (as I did before).
I'll have to check/test/upload it later, though, as the PC is unavailable at the moment.
I'll also have to hope that excluding the stop() command doesn't cause bugs with the rest of the file (the smiley animation and input box).
Copy link to clipboard
Copied
I looked at what you had in your dropbox on the client side (the smiley) and there is no stop() on the frame. That means the playhead will start at frame 1 and continue to the end of the animation (80 frames, 24fps, 3.3 seconds), and then loop, re-creating the socket connection and running all of the same code again. So there's one big problem.
What you want to do is make sure that code does not get run twice. There are several strategies to prevent this.
On frame 1 you could check for the existence of an object or variable, and based on that, you can decide to execute the code in that frame, or ignore it. Since you're creating a brand new socket on the first frame, you could check if it doesn't already exist, e.g.:
if (!sock)
{
// run ALL of that init code here..
}
Or, probably a bit better, you could move your smiley animation off frame 1 and when you want to loop back, use the command gotoAndPlay(#) to return to the first frame of the smiley animation. Because you never return to frame #1 again you don't need to worry about your code executing more than once. Here's what the timeline and script might look like with that scenario:
Here you can see the timeline is moved out 5 frames. On the last frame the script tells the playhead to go to frame 5, so it doesn't execute all the socket code on frame #1.
You could also nest your smiley animation in a single clip keeping the document to 1 frame (1 frame documents don't continuously execute the script on the single frame, it just executes once).
Bottom line, that's a big problem in the code.
I also noticed when you pasted in the timer code you mis-matched braces. Right after I declared my timer (consult the pic above) I closed off that function. You pasted that brace in the next function, which is a syntax error big enough to halt things as well. Be sure you stick closely to what's typed in code.
I always go away for the weekend but if there's a dropbox to something new on Monday I will see if I can help fix up your code. Until then, take a shot at it yourself, running the syntax checker. But remember, you can have valid syntax but still be running the wrong logic, like the example above with the missing brace:
The code looked like this:
var timer1:Timer = new Timer(300000, 0); // 0 here, running infinitely!
// now with it set to 1 it will only ever fire off 1 time
timer1.addEventListener(TimerEvent.TIMER, handleTimer);
timer1.start();
// MISSING BRACE!
// .. every 5 minutes write this to the socket
function handleTimer(e:TimerEvent):void
{
clientSockets[0].writeUTFBytes("Some message here after 5 minutes");
clientSockets[0].flush();
}
} // extra brace here, oops!
But should have looked like this:
var timer1:Timer = new Timer(300000, 1);
// now with it set to 1 it will only ever fire off 1 time
timer1.addEventListener(TimerEvent.TIMER, handleTimer);
timer1.start();
} // END FUNCTION
// .. every 5 minutes write this to the socket
function handleTimer(e:TimerEvent):void
{
clientSockets[0].writeUTFBytes("Some message here after 5 minutes");
clientSockets[0].flush();
}
That is valid code because you can nest a function declaration inside another function declaration, so Flash will not tell you it's wrong. But you can clearly see that wasn't correct. The handleTimer() function became a part of the previous function. Also you had your 5 minute timer set to fire off infinitely by using 0. That may be what you wanted however. Take a look over your code and my screenshot.
Copy link to clipboard
Copied
Ooh, that explains quite a bit, yeah.
I actually caught the brace error earlier (copied it to be exact to how you did it) - will have to re-check it though again.
I assume 'moving' the frames is as simple as 'dragging' them them all five frames forwards, or mass selecting + pasting? Or is it more arduous (re-do most of the things)?

