Flex XmlSocket 跨域通信
閑來無事,溫習了一下Socket編程,客戶端基于FlexBuilder3.0,服務器基于VS2010C#開發。如下運行效果圖:
登錄界面:

登錄后界面:

如果姓名有重復登錄,系統會提示:

多個界面交互:

服務器截圖:

客戶端代碼:
代碼
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
backgroundGradientAlphas="[1.0, 0.81]" backgroundGradientColors="[#166065, #93F0F6]">
<mx:Style>
Application{
fontSize:12px;
}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.formatters.DateFormatter;
import flash.events.Event;
import flash.events.DataEvent;
import mx.controls.Alert;
import flash.system.*;
private var socket:XMLSocket;
private var mydate:Date=new Date();
private var formatter:DateFormatter=new DateFormatter();
//連接服務器
private function ConnServer():void{
//formatter.formatString="YYYY-MM-DD JJ:NN:SS";
if(txtIP.text=="" || txtPort.text==''|| userName.text==''){
Alert.yesLabel="確定";
Alert.show("不能為空請填寫!","提示",1);
return;
}
formatter.formatString="JJ:NN:SS";
currentState="loginState";
loginPanel.title="客戶端-"+userName.text;
socket=new XMLSocket();
//添加事件偵聽
socket.addEventListener(Event.CONNECT,OnConn);
socket.addEventListener(DataEvent.DATA,OnReceived);
socket.addEventListener(IOErrorEvent.IO_ERROR,isErrorHandler);
socket.connect(txtIP.text,int(txtPort.text));
textReceive.addEventListener(FlexEvent.VALUE_COMMIT,OnValueChange);
}
//設置接收信息區的滾動條
private function OnValueChange(evt:FlexEvent):void{
textReceive.verticalScrollPosition=textReceive.maxVerticalScrollPosition;
}
//連接完成執行函數
private function OnConn(evt:Event):void{
textReceive.htmlText="*******************<font color='#ff0000'>登錄成功</font>********************\n";
//向服務器發送指令
socket.send("CONN|"+userName.text);
}
//接收服務器轉播信息
private function OnReceived(evt:DataEvent):void{
if(evt.data=="Failed"){//接收失敗重新登錄連接服務器,客戶端轉向登錄狀態
currentState="";
loginPanel.title="客戶端-未連接";
textReceive.text="";
Alert.yesLabel="確定";
Alert.show("姓名【"+userName.text+"】已被占用!","提示",1);
}else{//接收數據顯示在客戶端信息區
var arry:Array=evt.data.split('|',evt.data.length);
textReceive.text+="【"+arry[0]+" 在"+formatter.format(mydate)+"】說:\n"+arry[1]+"\n";
}
}
//連接服務器報錯處理
private function isErrorHandler(evt:IOErrorEvent):void{
currentState="";
loginPanel.title="客戶端-未連接";
Alert.yesLabel="確定";
Alert.show(evt.text,"提示",1,this);
}
//客戶端向服務器發送消息
private function sendMsg():void{
if(txtIP.text=="" || txtPort.text==""){
currentState="";
loginPanel.title="客戶端-未連接";
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
backgroundGradientAlphas="[1.0, 0.81]" backgroundGradientColors="[#166065, #93F0F6]">
<mx:Style>
Application{
fontSize:12px;
}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.formatters.DateFormatter;
import flash.events.Event;
import flash.events.DataEvent;
import mx.controls.Alert;
import flash.system.*;
private var socket:XMLSocket;
private var mydate:Date=new Date();
private var formatter:DateFormatter=new DateFormatter();
//連接服務器
private function ConnServer():void{
//formatter.formatString="YYYY-MM-DD JJ:NN:SS";
if(txtIP.text=="" || txtPort.text==''|| userName.text==''){
Alert.yesLabel="確定";
Alert.show("不能為空請填寫!","提示",1);
return;
}
formatter.formatString="JJ:NN:SS";
currentState="loginState";
loginPanel.title="客戶端-"+userName.text;
socket=new XMLSocket();
//添加事件偵聽
socket.addEventListener(Event.CONNECT,OnConn);
socket.addEventListener(DataEvent.DATA,OnReceived);
socket.addEventListener(IOErrorEvent.IO_ERROR,isErrorHandler);
socket.connect(txtIP.text,int(txtPort.text));
textReceive.addEventListener(FlexEvent.VALUE_COMMIT,OnValueChange);
}
//設置接收信息區的滾動條
private function OnValueChange(evt:FlexEvent):void{
textReceive.verticalScrollPosition=textReceive.maxVerticalScrollPosition;
}
//連接完成執行函數
private function OnConn(evt:Event):void{
textReceive.htmlText="*******************<font color='#ff0000'>登錄成功</font>********************\n";
//向服務器發送指令
socket.send("CONN|"+userName.text);
}
//接收服務器轉播信息
private function OnReceived(evt:DataEvent):void{
if(evt.data=="Failed"){//接收失敗重新登錄連接服務器,客戶端轉向登錄狀態
currentState="";
loginPanel.title="客戶端-未連接";
textReceive.text="";
Alert.yesLabel="確定";
Alert.show("姓名【"+userName.text+"】已被占用!","提示",1);
}else{//接收數據顯示在客戶端信息區
var arry:Array=evt.data.split('|',evt.data.length);
textReceive.text+="【"+arry[0]+" 在"+formatter.format(mydate)+"】說:\n"+arry[1]+"\n";
}
}
//連接服務器報錯處理
private function isErrorHandler(evt:IOErrorEvent):void{
currentState="";
loginPanel.title="客戶端-未連接";
Alert.yesLabel="確定";
Alert.show(evt.text,"提示",1,this);
}
//客戶端向服務器發送消息
private function sendMsg():void{
if(txtIP.text=="" || txtPort.text==""){
currentState="";
loginPanel.title="客戶端-未連接";
return;
}
if(socket.connected){
if(textSend.text==""){
Alert.yesLabel="確定";
Alert.show("發送內容不能為空!","提示",1);
return;
}
socket.send(userName.text+"|"+textSend.text);
textReceive.text+="【"+userName.text+" 在"+formatter.format(mydate)+"】說:\n"+textSend.text+"\n";
textSend.text="";
}
else{
currentState="";
loginPanel.title="客戶端-未連接";
Alert.yesLabel="確定";
Alert.show("登錄服務器失敗,請從新登錄!","提示",1);
}
}
]]>
</mx:Script>
<!--登錄成功后把Panel的狀態設為loginState-->
<mx:states>
<mx:State name="loginState">
<mx:RemoveChild target="{label1}"/>
<mx:RemoveChild target="{txtIP}"/>
<mx:RemoveChild target="{txtPort}"/>
<mx:RemoveChild target="{label2}"/>
<mx:RemoveChild target="{btnCon}"/>
<mx:SetProperty target="{textReceive}" name="height" value="212"/>
<mx:SetProperty target="{textReceive}" name="y" value="10"/>
<mx:RemoveChild target="{label3}"/>
<mx:RemoveChild target="{userName}"/>
</mx:State>
</mx:states>
<!--登錄成功后播放2秒鐘動畫把Panel狀態改為loginState-->
<mx:transitions>
<mx:Transition>
<mx:Iris duration="2000" targets="{[loginPanel]}">
</mx:Iris>
</mx:Transition>
</mx:transitions>
<!--客戶端窗口設計-->
<mx:Panel id="loginPanel" width="423" height="358" layout="absolute" horizontalCenter="0" y="131" title="客戶端" backgroundAlpha="0.8">
<mx:TextArea id="textReceive" x="10" y="45" width="383" height="177"/>
<mx:TextArea id="textSend" x="10" y="230" width="323" height="76"/>
<mx:Button id="btnSend" click="sendMsg()" y="229" label="發送" height="77" x="341" fillAlphas="[1.0, 1.0, 0.9, 0.9]" fillColors="[#25B9BE, #DAE9EA, #148A8E, #3CEEF4]"/>
<mx:Label x="10" y="10" text="IP:" fontWeight="bold" id="label1"/>
<mx:TextInput id="txtIP" x="35" y="8" width="97" text="192.168.1.35"/>
<mx:Label x="134" y="10" text="Port:" fontWeight="bold" id="label2"/>
<mx:TextInput id="txtPort" x="170" y="8" width="44" text="1234"/>
<mx:Button id="btnCon" click="ConnServer()" x="341" y="9" label="登錄" fillAlphas="[1.0, 1.0]" fillColors="[#F8A5BB, #F20C5D]" width="52"/>
<mx:Label x="214" y="11" text="姓名:" fontWeight="bold" id="label3"/>
<mx:TextInput id="userName" x="255" y="8" width="80" text="風行者"/>
</mx:Panel>
</mx:Application>
}
if(socket.connected){
if(textSend.text==""){
Alert.yesLabel="確定";
Alert.show("發送內容不能為空!","提示",1);
return;
}
socket.send(userName.text+"|"+textSend.text);
textReceive.text+="【"+userName.text+" 在"+formatter.format(mydate)+"】說:\n"+textSend.text+"\n";
textSend.text="";
}
else{
currentState="";
loginPanel.title="客戶端-未連接";
Alert.yesLabel="確定";
Alert.show("登錄服務器失敗,請從新登錄!","提示",1);
}
}
]]>
</mx:Script>
<!--登錄成功后把Panel的狀態設為loginState-->
<mx:states>
<mx:State name="loginState">
<mx:RemoveChild target="{label1}"/>
<mx:RemoveChild target="{txtIP}"/>
<mx:RemoveChild target="{txtPort}"/>
<mx:RemoveChild target="{label2}"/>
<mx:RemoveChild target="{btnCon}"/>
<mx:SetProperty target="{textReceive}" name="height" value="212"/>
<mx:SetProperty target="{textReceive}" name="y" value="10"/>
<mx:RemoveChild target="{label3}"/>
<mx:RemoveChild target="{userName}"/>
</mx:State>
</mx:states>
<!--登錄成功后播放2秒鐘動畫把Panel狀態改為loginState-->
<mx:transitions>
<mx:Transition>
<mx:Iris duration="2000" targets="{[loginPanel]}">
</mx:Iris>
</mx:Transition>
</mx:transitions>
<!--客戶端窗口設計-->
<mx:Panel id="loginPanel" width="423" height="358" layout="absolute" horizontalCenter="0" y="131" title="客戶端" backgroundAlpha="0.8">
<mx:TextArea id="textReceive" x="10" y="45" width="383" height="177"/>
<mx:TextArea id="textSend" x="10" y="230" width="323" height="76"/>
<mx:Button id="btnSend" click="sendMsg()" y="229" label="發送" height="77" x="341" fillAlphas="[1.0, 1.0, 0.9, 0.9]" fillColors="[#25B9BE, #DAE9EA, #148A8E, #3CEEF4]"/>
<mx:Label x="10" y="10" text="IP:" fontWeight="bold" id="label1"/>
<mx:TextInput id="txtIP" x="35" y="8" width="97" text="192.168.1.35"/>
<mx:Label x="134" y="10" text="Port:" fontWeight="bold" id="label2"/>
<mx:TextInput id="txtPort" x="170" y="8" width="44" text="1234"/>
<mx:Button id="btnCon" click="ConnServer()" x="341" y="9" label="登錄" fillAlphas="[1.0, 1.0]" fillColors="[#F8A5BB, #F20C5D]" width="52"/>
<mx:Label x="214" y="11" text="姓名:" fontWeight="bold" id="label3"/>
<mx:TextInput id="userName" x="255" y="8" width="80" text="風行者"/>
</mx:Panel>
</mx:Application>
跨域訪問安全沙箱設置:
如果不設置,是不能通信的并且包如下錯誤:

登錄客戶端時,客戶端會向服務器發送字符串:<policy-file-request/>,在服務器端只需檢測該字符串,收到后回發一條如下信息:即可解決安全沙箱沖突問題。
string onemessage = "<cross-domain-policy><allow-access-from domain=\"" + "*" + "\" to-ports=\"1234\"/></cross-domain-policy>\0";
byte[] buffer = Encoding.UTF8.GetBytes(onemessage);
socket.Send(buffer);
服務器端代碼:請參考以前發表的【C#局域網通信】(C#.net分類里)
http://www.rzrgm.cn/Xingsoft-555/archive/2009/12/13/1622829.html


浙公網安備 33010602011771號