闲来无事,温习了一下Socket编程,客户端基于FlexBuilder3.0,服务器基于VS2010C#开发。如下运行效果图:
登录界面:
登录后界面:
如果姓名有重复登录,系统会提示:
多个界面交互:
服务器截图:
客户端代码:
< 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 = " 客户端-未连接 " ;
}
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.cnblogs.com/Xingsoft-555/archive/2009/12/13/1622829.html