Sending requests from Flash - actionscript-3

Here is a simplified version of some Flash code I have been using to get username of the person playing the game:
var req:URLLoader = new URLLoader();
req.addEventListener(Event.COMPLETE, onLoaded);
req.load(new URLRequest(baseURL + "php/account.php?getUsername"));
function onLoaded(e:Event):void {
if(e.target.data == "Guest") {
LoadingText.text = "Welcome, Guest!"
}
else {
LoadingText.text = "Welcome, " + e.target.data + "!";
}
}
php/account.php?getUsername just gets the username from a PHP session variable and outputs it.
Using something like Tamper Data for Firefox, I can see the request being sent from Flash and can even edit it if I wanted.
This approach feels very slow compared to other online games, and when trying to reverse engineer other games to see how they manage something like this, for some games, requests wont show up in Tamper Data.
So I wonder, are there any alternative ways to send requests in Flash which are faster and more efficient? I don't need anything fancy such as sending post data or editing the referral URL.
Thanks.

Most probably other games use socket connections. This is reason why you don't see request in Tamper Data and why they have better performance.
In case of socket connection you open connection to server once and you can make as many requests as you wish.
With HTTP, TCP connection is opened and closed for each request this affects performance.
With socket connections you can avoid HTTP protocol completely, you can design your protocol much lighter than HTTP. In fact no one uses HTTP when you need high performance.
See flash socket documentation here: Socket
P.S.
For high performance it is better to use UDP instead of TCP but flash sockets are limited to TCP so you don't need to take care of this.

Related

Actionscript services stop functioning

I have built a complex AIR application which has been successfully running for quite some time of many PCs. Unfortunately, I have a plaguing problem with internet connectivity and I was wondering if anyone had encountered this issue before.
Every once in a while, the program will completely stop talking to the internet (all services start faulting). I wrote special code in my program to monitor the situation in which I use two different services to contact the same server.
The first service:
var req:URLRequest = new URLRequest("myURL.com");
this.urlMonitor = new URLMonitor(req, [200, 304]); // Acceptable status codes
this.urlMonitor.pollInterval = 60 * 1000; // Every minute
this.urlMonitor.addEventListener(StatusEvent.STATUS, onStatusChange);
this.urlMonitor.start();
private function onStatusChange(e:StatusEvent):void
{
if (this.urlMonitor.available)
{
pollStatusOnline = true;
Online = true;
}
else
{
pollStatusOnline = false;
Online = false;
}
}
The secondary method is a normal HTTP Service call:
checkInService = new HTTPService();
checkInService.method = "POST";
checkInService.addEventListener(ResultEvent.RESULT,sendResult);
checkInService.addEventListener(FaultEvent.FAULT, faultResult);
checkInService.addEventListener(InvokeEvent.INVOKE, invokeAttempt);
checkInService.url = "myURL.com";
checkInService.concurrency = Concurrency.LAST;
checkInService.send(params);
These two services point to the same location and work 98% of the time. Sometimes, after a few hours, I have noticed that both services no longer can connect to the website. The HTTP Service returns a StatusCode 0. I am able to open command prompt and ping the server directly with no problem from the PC which is failing. The services will not function again until the program is restarted.
I have been working on this issue for many months now without resolution. If anyone is able to even point me in a somewhat possible, maybe this might be the problem, possibly, direction, I would really appreciate it.
Thank you in advance.
Check the code value of the StatusEvent you receive from the URLMonitor - this might give more info than the HTTPService (you might also want to try passing a null value to URLMonitor constructor, to widen the acceptable status codes).
If you have access to the server(s?) in question, check their logs. Could the server config have changed such that it might now consider such frequent requests as flooding?
You should also be able to use an HTTP debugger like Fiddler or Charles on the client machine to see more information about the requests going out of your application.

What's best options for video streaming or max data transfer using SuperWebSocket

Minimum To Achieve:- Send nearly or more than 1 mb/second to other websocket clients.
Questions:--
Is it possible video streaming with SuperWebSocket?
What options/features of SuperWebSocket can be used like Asynch
mode/JsonCommands/CustomSession/etc to achieve fastest data
transfer?
How to sequence a big data sent in chunks but if received without any order at client or server side? Is there anything built in to sequence these chunks or I have to manually send sequence nos in message itself?
What I have tried:--
Multiple secure sessions with same port and different paths in javascript code
ws = new WebSocket(wss://localhost:8089/1/1)
ws = new WebSocket(wss://localhost:8089/2/2)
ws = new WebSocket(wss://localhost:8089/3/3)
with above sessions I send large data in chunks but it's not receiving in expected order at server/client side and also after successfully sending large chunk (size=55000kb) that session closes automatically!
I am looking into sample projects of SuperWebSocket but not sure where to go! I am open to try any option inside SuperWebsocket. Thanks
1) I am not sure it does, but if it provides an API to send Byte[], it may be enough.
2) No idea about this one, the documentation may explain it.
3) What do you mean without order? WebSockets is TCP based, so data segments sent in the same connection will arrive in the same order they were sent.
4) Why would you open different connections to the same site? There is also probably limitations about the connections that you can open to the same host. One should be OK, open several is not going to increment your bandwidth, only will increment your problems.
I develop a WebSocket server component that handles messages as Stream derived objects and has an acceptable performance so far, you may like to give it a try.

Game + Web Server using ExpressJS

I'm currently trying to develop a simple Flash game which talks to a node.js server.
My question is this:
How might I go about making a server which differentiates web requests from game requests?
Here are the details of what I've done:
Previously, I used the net and static modules to handle requests from the game client and the browser, respectively.
TwoServers.js
// Web server
var file = new staticModule.Server('./public');
http.createServer(function(req, res){
req.addListener('end', function(){
file.serve(req, res, function(err, result){
// do something
});
});
}).listen(port1, "127.0.0.1");
// Game Server
var server = net.createServer(function(socket)
{
// handle messages to/from Flash client
socket.setEncoding('utf8');
socket.write('foo');
socket.on('data', onMessageReceived);
});
server.listen(port2, "127.0.0.1");
I'd like to do the above with just an Express server listening in on a single port, but I'm not sure how to go about doing that.
Here's what I'm thinking it might look like (doesn't actually work):
OneServer.js
var app = express();
app.configure(function()
{
// ...
app.use('/',express.static(path.join(__dirname, 'public'))); // The static server
});
app.get('/', function(req, res) // This is incorrect (expects http requests)
{
// Handle messages to/from Flash client
var socket = req.connection;
socket.setEncoding('utf8');
socket.write('foo');
socket.on('data', onMessageReceived);
});
app.listen(app.get('port')); // Listen in on a single port
But I'd like to be able to differentiate from web page requests and requests from the game.
Note: Actionscript's XMLSocket makes TCP requests, so using app.get('/') is incorrect for two reasons:
When Flash writes to the socket, it isn't using the http protocol, so app.get('/') will not be fired when the game tries to connect.
Since I don't have access to correct the net.Socket object, I cannot expect to be reading or writing from/to the correct socket. Instead, I'll be reading/writing from/to the socket associated with the web page requests.
Any help on this would be much appreciated (especially if I'm reasoning about this the wrong way).
When a TCP connection is opened to a given port, the server (Node + Express) has no way of telling who made that connection (whether it's a browser or your custom client).
Therefore, your custom client must speak HTTP if it wishes to communicate with the Express server sitting on port 80. Otherwise, the data you send over a freshly opened socket (in your custom protocol) will just look like garbage to Express, and it will close the connection.
However, this doesn't mean you can't get a TCP stream to speak a custom protocol over – you just have to speak HTTP first and ask to switch protocols. HTTP provides a mechanism exactly to accomplish this (the Upgrade header), and in fact it is how WebSockets are implemented.
When your Flash client first opens a TCP connection to your server, it should send: (note line breaks MUST be sent as CRLF characters, aka \r\n)
GET /gamesocket HTTP/1.1
Upgrade: x-my-custom-protocol/1.0
Host: example.com
Cache-Control: no-cache
​
The value of Upgrade is your choice, Host MUST be sent for all HTTP requests, and the Cache-Control header ensures no intermediate proxies service this request. Notice the blank line, which indicates the request is complete.
The server responds:
HTTP/1.1 101 Switching Protocols
Upgrade: x-my-custom-protocol/1.0
Connection: Upgrade
​
Again, a blank line indicates the headers are complete, and after that final CRLF, you are now free to send any data you like in any format over the TCP connection.
To implement the server side of this:
app.get('/gamesocket', function(req, res) {
if (req.get('Upgrade') == 'x-my-custom-protocol/1.0') {
res.writeHead(101, { Upgrade: req.get('Upgrade'), Connection: 'Upgrade' });
// `req.connection` is the raw net.Socket object
req.connection.removeAllListeners(); // make sure Express doesn't listen to the data anymore... we've got it from here!
// now you can do whatever with the socket
req.connection.setEncoding('utf8');
req.connection.write('foo');
req.connection.on('data', onMessageReceived);
} else res.send(400); // bad request
});
Of course, remember that TCP is not a message-based protocol, it only provides a stream, and thus the data events of a Socket can either fragment a single logical message into multiple events or even include several logical messages in a single event. Be prepared to manually buffer data.
Your other option here is to use socket.io, which implements a WebSockets server plus its own protocol on top of the WebSockets protocol. The WebSockets protocol is message-based. It mostly works just like I've outlined here, and then after HTTP negotiation adds a message framing layer on top of the TCP connection so that the application doesn't have to worry about the data stream. (Using WebSockets also opens the possibility of connecting to your server from a HTML page if necessary.)
There is a Flash socket.io client available.

Adobe AIR, URLRequest, and local ports

I'm looking at writing an app with Adobe AIR, but I wanted to figure out if this is feasible with the platform first. (Mostly new to Flash and AIR)
What I would like to do is know ahead of time what local port a URLRequest will be using. If possible, I would like to hold a connection open even and keep using the same socket.
What I'm basically trying to accomplish is doing some NAT-Traversal and port negotiation ahead of time. Once I have both the client and the server negotiated, I'd like them to connect and basically use HTTP in a peer-to-peer way to stream media, like this sample:
var s = new air.Sound();
var url = "http://www.example.com/sounds/bigSound.mp3";
var req = new air.URLRequest(url);
var context = new air.SoundLoaderContext(8000, true);
s.load(req, context);
s.play();
The problem is that I don't see this happening unless I can get some information from AIR on what ports it's planning to use. I would be OK with creating my own Socket connections to the server and using them, but I would need a way to leverage the Sound framework to stream in the same way from a socket.
Ideas? Thoughts? Thanks!
Even if you managed to guess which port AIR is going to use on your device, it is not going to be very helpful, since there is a reasonably high probability that your NAT will translate it to another value IF your AIR device has a private IP address.
This issue does not happen if your AIR server has a public IP address. Most often, you can configure the server's NAT/Router to forward traffic as is. A port scan from the WAN will quickly tell you which port is used.
If you want to 'hijack' an outbound connection created by AIR itself, then you might try to have it contact a special server peer you have implemented which will forward traffic from and to it. Not simple, but possible. Basically you would collect holes punched in the NAT by the server.

How does facebook, gmail send the real time notification?

I have read some posts about this topic and the answers are comet, reverse ajax, http streaming, server push, etc.
How does incoming mail notification on Gmail works?
How is GMail Chat able to make AJAX requests without client interaction?
I would like to know if there are any code references that I can follow to write a very simple example. Many posts or websites just talk about the technology. It is hard to find a complete sample code. Also, it seems many methods can be used to implement the comet, e.g. Hidden IFrame, XMLHttpRequest. In my opinion, using XMLHttpRequest is a better choice. What do you think of the pros and cons of different methods? Which one does Gmail use?
I know it needs to do it both in server side and client side.
Is there any PHP and Javascript sample code?
The way Facebook does this is pretty interesting.
A common method of doing such notifications is to poll a script on the server (using AJAX) on a given interval (perhaps every few seconds), to check if something has happened. However, this can be pretty network intensive, and you often make pointless requests, because nothing has happened.
The way Facebook does it is using the comet approach, rather than polling on an interval, as soon as one poll completes, it issues another one. However, each request to the script on the server has an extremely long timeout, and the server only responds to the request once something has happened. You can see this happening if you bring up Firebug's Console tab while on Facebook, with requests to a script possibly taking minutes. It is quite ingenious really, since this method cuts down immediately on both the number of requests, and how often you have to send them. You effectively now have an event framework that allows the server to 'fire' events.
Behind this, in terms of the actual content returned from those polls, it's a JSON response, with what appears to be a list of events, and info about them. It's minified though, so is a bit hard to read.
In terms of the actual technology, AJAX is the way to go here, because you can control request timeouts, and many other things. I'd recommend (Stack overflow cliche here) using jQuery to do the AJAX, it'll take a lot of the cross-compability problems away. In terms of PHP, you could simply poll an event log database table in your PHP script, and only return to the client when something happens? There are, I expect, many ways of implementing this.
Implementing:
Server Side:
There appear to be a few implementations of comet libraries in PHP, but to be honest, it really is very simple, something perhaps like the following pseudocode:
while(!has_event_happened()) {
sleep(5);
}
echo json_encode(get_events());
The has_event_happened function would just check if anything had happened in an events table or something, and then the get_events function would return a list of the new rows in the table? Depends on the context of the problem really.
Don't forget to change your PHP max execution time, otherwise it will timeout early!
Client Side:
Take a look at the jQuery plugin for doing Comet interaction:
Project homepage: http://plugins.jquery.com/project/Comet
Google Code: https://code.google.com/archive/p/jquerycomet/ - Appears to have some sort of example usage in the subversion repository.
That said, the plugin seems to add a fair bit of complexity, it really is very simple on the client, perhaps (with jQuery) something like:
function doPoll() {
$.get("events.php", {}, function(result) {
$.each(result.events, function(event) { //iterate over the events
//do something with your event
});
doPoll();
//this effectively causes the poll to run again as
//soon as the response comes back
}, 'json');
}
$(document).ready(function() {
$.ajaxSetup({
timeout: 1000*60//set a global AJAX timeout of a minute
});
doPoll(); // do the first poll
});
The whole thing depends a lot on how your existing architecture is put together.
Update
As I continue to recieve upvotes on this, I think it is reasonable to remember that this answer is 4 years old. Web has grown in a really fast pace, so please be mindful about this answer.
I had the same issue recently and researched about the subject.
The solution given is called long polling, and to correctly use it you must be sure that your AJAX request has a "large" timeout and to always make this request after the current ends (timeout, error or success).
Long Polling - Client
Here, to keep code short, I will use jQuery:
function pollTask() {
$.ajax({
url: '/api/Polling',
async: true, // by default, it's async, but...
dataType: 'json', // or the dataType you are working with
timeout: 10000, // IMPORTANT! this is a 10 seconds timeout
cache: false
}).done(function (eventList) {
// Handle your data here
var data;
for (var eventName in eventList) {
data = eventList[eventName];
dispatcher.handle(eventName, data); // handle the `eventName` with `data`
}
}).always(pollTask);
}
It is important to remember that (from jQuery docs):
In jQuery 1.4.x and below, the XMLHttpRequest object will be in an
invalid state if the request times out; accessing any object members
may throw an exception. In Firefox 3.0+ only, script and JSONP
requests cannot be cancelled by a timeout; the script will run even if
it arrives after the timeout period.
Long Polling - Server
It is not in any specific language, but it would be something like this:
function handleRequest () {
while (!anythingHappened() || hasTimedOut()) { sleep(2); }
return events();
}
Here, hasTimedOut will make sure your code does not wait forever, and anythingHappened, will check if any event happend. The sleep is for releasing your thread to do other stuff while nothing happens. The events will return a dictionary of events (or any other data structure you may prefer) in JSON format (or any other you prefer).
It surely solves the problem, but, if you are concerned about scalability and perfomance as I was when researching, you might consider another solution I found.
Solution
Use sockets!
On client side, to avoid any compatibility issues, use socket.io. It tries to use socket directly, and have fallbacks to other solutions when sockets are not available.
On server side, create a server using NodeJS (example here). The client will subscribe to this channel (observer) created with the server. Whenever a notification has to be sent, it is published in this channel and the subscriptor (client) gets notified.
If you don't like this solution, try APE (Ajax Push Engine).
Hope I helped.
According to a slideshow about Facebook's Messaging system, Facebook uses the comet technology to "push" message to web browsers. Facebook's comet server is built on the open sourced Erlang web server mochiweb.
In the picture below, the phrase "channel clusters" means "comet servers".
Many other big web sites build their own comet server, because there are differences between every company's need. But build your own comet server on a open source comet server is a good approach.
You can try icomet, a C1000K C++ comet server built with libevent. icomet also provides a JavaScript library, it is easy to use as simple as:
var comet = new iComet({
sign_url: 'http://' + app_host + '/sign?obj=' + obj,
sub_url: 'http://' + icomet_host + '/sub',
callback: function(msg){
// on server push
alert(msg.content);
}
});
icomet supports a wide range of Browsers and OSes, including Safari(iOS, Mac), IEs(Windows), Firefox, Chrome, etc.
Facebook uses MQTT instead of HTTP. Push is better than polling.
Through HTTP we need to poll the server continuously but via MQTT server pushes the message to clients.
Comparision between MQTT and HTTP: http://www.youtube.com/watch?v=-KNPXPmx88E
Note: my answers best fits for mobile devices.
One important issue with long polling is error handling.
There are two types of errors:
The request might timeout in which case the client should reestablish the connection immediately. This is a normal event in long polling when no messages have arrived.
A network error or an execution error. This is an actual error which the client should gracefully accept and wait for the server to come back on-line.
The main issue is that if your error handler reestablishes the connection immediately also for a type 2 error, the clients would DOS the server.
Both answers with code sample miss this.
function longPoll() {
var shouldDelay = false;
$.ajax({
url: 'poll.php',
async: true, // by default, it's async, but...
dataType: 'json', // or the dataType you are working with
timeout: 10000, // IMPORTANT! this is a 10 seconds timeout
cache: false
}).done(function (data, textStatus, jqXHR) {
// do something with data...
}).fail(function (jqXHR, textStatus, errorThrown ) {
shouldDelay = textStatus !== "timeout";
}).always(function() {
// in case of network error. throttle otherwise we DOS ourselves. If it was a timeout, its normal operation. go again.
var delay = shouldDelay ? 10000: 0;
window.setTimeout(longPoll, delay);
});
}
longPoll(); //fire first handler