02-15-2008, 02:18 PM
|
#2
|
|
|
I didn't know there was any way to get around the policy-file-request.
However, it is easy to implement in your socket server. Just send the policy file on socket_accept.
As you probably found out, when connecting to a socket server with AS3, flash will first send a request for the policy file, then disconnect, and if the appropriate policy file was received, it will connect again. Since the policy file is an xml format, you can strip it out of your received messages in the flash client.
Here's my basic chat solution, which sends the policy file both times the client connects: (it's only a few bytes, so it doesn't really affect bandwidth):
AS3:
PHP Code:
package{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.net.*;
public class chat extends Sprite {
private var socket:XMLSocket;
private var msgArea:TextField = new TextField();
private var inputMsg:TextField = new TextField();
private var lastMessage:String = "";
private var connected:Boolean = false;
public function chat() {
msgArea.x=15;
msgArea.y=15;
msgArea.width=450;
msgArea.height=150;
msgArea.multiline=msgArea.border=msgArea.background=true;
addChild(msgArea);
inputMsg.x=15;
inputMsg.y=170;
inputMsg.width=415;
inputMsg.height=20;
inputMsg.type=TextFieldType.INPUT;
inputMsg.multiline=false;
inputMsg.selectable=inputMsg.border=inputMsg.background=true;
inputMsg.text="127.0.0.1"; // change to your IP
addChild(inputMsg);
var pushMsg:Sprite = new Sprite();
var pushText:TextField = new TextField();
pushText.x=400;
pushText.y=170;
pushText.selectable=false;
pushText.autoSize='center';
pushText.text='Send';
pushText.border=pushText.background=true;
pushMsg.useHandCursor=true;
pushMsg.addChild(pushText);
pushMsg.addEventListener(MouseEvent.MOUSE_DOWN, msgGo);
addChild(pushMsg);
socket = new XMLSocket();
configureListeners(socket);
msgArea.htmlText = lastMessage = "<b>Enter IP address of the server, then click the \"Send\" button</b>";
}
private function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.CLOSE, closeHandler);
dispatcher.addEventListener(Event.CONNECT, connectHandler);
dispatcher.addEventListener(DataEvent.DATA, dataHandler);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
}
private function securityErrorHandler(event:SecurityErrorEvent):void {
msgArea.htmlText += "<br>securityErrorHandler: " + event;
}
private function connectHandler(success:Boolean):void {
if (success) {
msgArea.htmlText = lastMessage + '<br>' + '<b>Server connection established!</b>';
lastMessage = '<b>Server connection established!</b>';
connected = true;
} else {
msgArea.htmlText = lastMessage + '<br>' + '<b>Server connection failed!</b>';
lastMessage = '<b>Server connection failed!</b>';
}
}
private function closeHandler(event:Event):void {
msgArea.htmlText = lastMessage + '<br>' + '<b>Server connection lost</b>';
lastMessage = '<b>Server connection lost</b>';
}
private function dataHandler(event:DataEvent):void {
msgArea.htmlText = lastMessage + '<br>' + event.data;
lastMessage = event.data;
}
private function msgGo(event:MouseEvent):void{
if(!connected){
msgArea.htmlText = lastMessage = "<b>Contacting Server...</b>";
socket.connect(inputMsg.text,9999); // change 9999 to your port
}else{
if (inputMsg.text != '') {
socket.send(inputMsg.text);
}
}
inputMsg.text = '';
}
}
}
AS2 implementation:
PHP Code:
createTextField('msgArea', getNextHighestDepth(), 15, 17, 450, 150);
with(msgArea){
border=background=html=wordWrap=mulitline=selectable=multiline=wordWrap=true;
}
createTextField('inputMsg', getNextHighestDepth(), 15, 170, 415, 20);
with(inputMsg){
border=background=true;
multiline=false;
type='input';
text='192.168.2.4';
}
createEmptyMovieClip('pushMsg',getNextHighestDepth());
pushMsg.createTextField('buttonText', pushMsg.getNextHighestDepth(), 455, 170, 0, 0);
with(pushMsg.buttonText){
border=background=true;
selectable=false;
autoSize='center';
text='Send';
}
mySocket = new XMLSocket();
connected = false;
mySocket.onConnect = function(success) {
if (success) {
msgArea.htmlText = lastMessage + '\n' + '<b>Server connection established!</b>';
lastMessage = '<b>Server connection established!</b>';
connected = true;
} else {
msgArea.htmlText = lastMessage + '\n' + '<b>Server connection failed!</b>';
lastMessage = '<b>Server connection failed!</b>';
}
};
mySocket.onClose = function() {
msgArea.htmlText = lastMessage + '\n' + '<b>Server connection lost</b>';
lastMessage = '<b>Server connection lost</b>';
};
var lastMessage = '';
XMLSocket.prototype.onData = function(msg) {
var elapsedTime = getTimer() - timer;
msgArea.htmlText = lastMessage + '\n' + msg + '\n' + elapsedTime;
lastMessage = msg;
};
msgArea.text = lastMessage = 'Enter IP address of the server, then click the \"Send\" button';
//--- Handle button click --------------------------------------
timer = 0;
function msgGO() {
if(!connected){
msgArea.htmlText = lastMessage = '<b>Contacting Server...</b>';
mySocket.connect(inputMsg.text, 9999);
}else{
if (inputMsg.text != '') {
timer = getTimer();
mySocket.send(inputMsg.text);
}
}
inputMsg.text = '';
}
pushMsg.onRelease = function() {
msgGO();
Selection.setFocus(inputMsg);
};
_keyListener = new Object();
Key.addListener(_keyListener);
_keyListener.onKeyDown=function(){
if(Key.getCode()==Key.ENTER){
pushMsg.onRelease();
}
};
Basic PHP socket server (use as a basis, NOT FOR PRODUCTION!):
PHP Code:
#!/usr/bin/php -q
<?php
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
echo "Enter Server IP:\n";
$address = trim(fgets(STDIN));
//$address = '192.168.2.4';
echo "Enter Port:\n";
$port = trim(fgets(STDIN));
//$port = 9999;
echo "Attempting to connect to $address:$port\n";
//---- Function to Send out Messages to Everyone Connected ----------------------------------------
function send_Message($allclient, $buf) {
global $client_list;
foreach($allclient as $client) {
if($client_list[$client]['state'] && $client_list[$client]['nick'] != ""){
socket_write($client, trim($buf).chr(0));
}
}
}
function who($allclient, $socket) {
global $client_list;
$buf = "";
$counter = 0;
foreach($allclient as $client) {
$buf.=$client_list[$client]['nick'].", ";
$counter++;
}
socket_write($socket, "There are $counter people in this room: $buf".chr(0));
}
function send_Single($socket, $buf) {
socket_write($socket, $buf.chr(0));
}
function shutDown($allclients, $master){
global $abort;
$abort = false;
foreach($allclients as $client){
echo "$client connection closed\n";
socket_close($client);
}
echo "$master connection closed\n";
socket_close($master);
echo "Server shutdown complete\n";
}
//---- Start Socket creation for PHP 5 Socket Server -------------------------------------
if (($master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
echo "socket_create() failed, reason: " . socket_strerror($master) . "\n";
}else{
echo "$master socket created\n";
}
socket_set_option($master, SOL_SOCKET,SO_REUSEADDR, 1);
if (($ret = socket_bind($master, $address, $port)) < 0) {
echo "socket_bind() failed, reason: " . socket_strerror($ret) . "\n";
}else{
echo "$ret socket bound to $address:$port\n";
}
if (($ret = socket_listen($master, 5)) < 0) {
echo "socket_listen() failed, reason: " . socket_strerror($ret) . "\n";
}else{
echo "$ret listening...\n";
}
$read_sockets = array($master);
$client_list = array($master);
$abort = true;
$policy_file =
'<'.'?xml version="1.0" encoding="UTF-8"?'.'>'.
'<cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd">'.
'<allow-access-from domain="*" to-ports="*" secure="false" />'.
'<site-control permitted-cross-domain-policies="master-only" />'.
'</cross-domain-policy>';
//---- Create Persistent Loop to continuously handle incoming socket messages ---------------------
while ($abort) {
$changed_sockets = $read_sockets;
$num_changed_sockets = socket_select($changed_sockets, $write = NULL, $except = NULL, NULL);
foreach($changed_sockets as $socket) {
if ($socket == $master) {
if (($client = socket_accept($master)) < 0) {
echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
continue;
} else {
echo "[connection]:$client\n";
array_push($read_sockets, $client);
$client_list[$client]['state'] = false;
$client_list[$client]['nick'] = "";
send_Single($client, $policy_file);
send_Single($client, "<b>Enter a nickname:<b>");
}
} else {
$bytes = socket_recv($socket, $buffer, 2048, 0);
if ($bytes == 0) {
$nick = $client_list[$socket]['nick'];
$iindex = array_search($socket, $client_list);
unset($client_list[$iindex]);
$index = array_search($socket, $read_sockets);
unset($read_sockets[$index]);
$allclients = $read_sockets;
array_shift($allclients);
if($client_list[$socket]['nick'] != "" && $client_list[$socket]['nick'] != "<policy-file-request/>"){
echo "[connection-terminated]:$socket\n";
send_Message($allclients, "$nick has left the room");
}
socket_close($socket);
}else{
if($bytes){
if($client_list[$socket]['state'] === false){
$tempBuf = trim($buffer);
$testCase = false;
foreach($read_sockets as $clients){
if ($client_list[$clients]['nick'] == $tempBuf) {
$testCase = true;
send_Single($socket, "Sorry, \"$tempBuf\" is already in use!");
send_Single($socket, "Please choose another nickname:");
break;
}
}
if(!$testCase){
$client_list[$socket]['nick'] = $tempBuf;
echo "$tempBuf assigned to $socket\n";
send_Single($socket, "Hello $tempBuf! Welcome to the game!");
$allclients = $read_sockets;
array_shift($allclients);
who($allclients, $socket);
if($client_list[$socket]['nick'] != "" && $tempBuf != "<policy-file-request/>"){
send_Message($allclients, $client_list[$socket]['nick']." has entered the game.");
}
$client_list[$socket]['state'] = true;
}
}else{
$allclients = $read_sockets;
array_shift($allclients);
if(trim($buffer) == "shut-down-server"){
shutDown($allclients, $master);
}else{
if(trim($buffer) == "/who"){
who($allclients, $socket);
}else{
send_Message($allclients, $client_list[$socket]['nick']." wrote: ".$buffer);
}
}
}
}
}
}
}
}
?>
|
|
|
02-15-2008, 07:56 PM
|
#5
|
|
|
Quote:
Originally Posted by Jerryscript
Do you have to have the server login done during preload?
If not, I'm not sure what your architecture is,
|
Architecture in brief:
First, visitor logs on web app. Web app loads preload swf. Preload swf authorizes itself trough URLLoad and loads bunch of xml's (settings and localization).
If everything is ok, main swf is loaded. After main swf is loaded, preload swf call init method in main swf, which initalize socket connection.
Socket class is wrapped in other class, called Dispatcher. That class encapsulates all functionality related to communication with socket, prepares data to be send and parses received data.
Main swf also communicate with web app, which serves xml's. Web app and socket server are on different domains.
One of solutions I have on my mind is to connect to socket in preload swf, using plain socket, and then to pass that socket to Dispatcher class. That solution is not clean, but worth of trying, and can be easly implemented by adding "externalSocket" method to Dispatcher class:
MainMovie.Dispatcher.externalSocket = new Socket(host,port);
|
|
|
02-16-2008, 04:24 AM
|
#7
|
|
|
Quote:
Originally Posted by Jerryscript
The error your getting is 2048?
|
No, just <policy-file-request/> is sent to socket server not to xml "policy" server on port 843
|
|
|
02-16-2008, 01:26 PM
|
#9
|
|
|
Quote:
Originally Posted by Jerryscript
So maybe Adobe listened and got rid of the need for a sub http level socket policy server?!? I sure hope so!
|
 Yeah, sure...
Did you, or anyone else, had similar situation as I?
|
|
|
04-12-2008, 05:14 AM
|
#14
|
|
|
Quote:
Originally Posted by looping
Hello
We find the problem, it sounds it's due to the way Adobe Handles the policy file request.
The message <Policy File Request/> is sent with the null character at the end and the anwser returned by your server on port 843, must include also the null character to terminate the message. that's why the problem seems to be random because it depends on the memory on you client. So you'll have to developp you own server because i don't know any program which will send the null character at the end of a message
|
Even after sending the policy-file with null termination character this problem is seem to be intermittently reproducible. Let me know whether it happens on your side or not
|
|
|
04-21-2008, 12:01 AM
|
#15
|
|
|
Quote:
Originally Posted by gp_svn
Even after sending the policy-file with null termination character this problem is seem to be intermittently reproducible. Let me know whether it happens on your side or not
|
Finally!!! we were able to make it work by opening master socket port 843 on the server and listening to <policy-file-request/> and then responding the master socket policy data
|
|
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
|
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 10:25 AM.
|
|