Flex Socket与Java通信这两天一直在flex的Socket ,现在终于懂了很多。由浅到深一步一步深入。慢慢体会实例,
Flex Socket与Java通信
这两天一直在flex的Socket ,现在终于懂了很多。由浅到深一步一步深入。慢慢体会实例,虽然实例都是在网上找的,但也经过了我的测试。我比较喜欢注释,也注释了很多。
跟着走你就会懂。。
?
Flex端 和 Java端, 先运行Java端启动服务。然后在测试Flex。
?
实例一:
Flex端:
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="349" height="326"
creationComplete="initApp()" showCloseButton="true" >
<mx:Script>
<![CDATA[
/**
当运行在服务tocmat上面是,安全沙漏箱问题
运行在本地文件上,正常
Why ?
?
这个问题,我在web上也测试了的,结果成功了。配置好策略文件
*/
private var socket:Socket;
internal function initApp():void{
socket = new Socket(); //new出来 ,这时候才能被使用
socket.connect("localhost",8080); //连接服务器 , 参数 host:String,prot:int
socket.addEventListener(Event.CONNECT,funConnect); //监听是否连接上服务器
socket.addEventListener(Event.CLOSE,funClose);//监听服务器是否关闭
}
private function funConnect(event:Event):void {
myText.text+="已经成功连接到服务器!\n";
}
private function funClose(event:Event):void {
myText.text+="和服务器断开!\n"
}
]]>
</mx:Script>
<mx:TextArea id="myText" x="10" y="10" width="285" height="250" />
</mx:TitleWindow>
Java 端:package f1.f1_005.socket;
import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;
public class Server1 {
public static void main(String[] args) {ServerSocket server = null;try {//使用指定的端口号创建了一服务器套接字对象。server = new ServerSocket(8888);System.out.println("服务器套接字已经被创建");while(true){System.out.println("等待客户机");//调用accept()方法来等待客户机的连接请求。 api:倾听一个连接被使这插座,接受它Socket socket = server.accept();?System.out.println("已与客户机连接");}} catch (IOException e) {System.out.println(e);e.printStackTrace();} finally {try {if(server!=null)server.close(); //关闭服务器套接字。如果一直没有客户机器提出连接请求,服务器套接字将会继续等待。} catch (IOException e) {e.printStackTrace();}?}}
}
-------------------------------------------------------
实例二:Flex端:<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp();"><mx:Script><![CDATA[private var socket:Socket = new Socket();//定义Socketinternal function initApp():void{socket.connect("127.0.0.1",8888);//连接服务器socket.addEventListener(Event.CONNECT, funConnect);socket.addEventListener(Event.CLOSE, funClose);}internal function funConnect(e:Event):void{myText.text+="连接已建立 \n";}internal function funClose(e:Event):void{myText.text+="连接已关闭 \n";}internal function sendMessage(msg:String):void{ //发送数据对应按钮click事件var message:ByteArray = new ByteArray();//新建一个ByteArray存放数据//写入数据,writeUTFBytes方法,以utf-8格式传数据避免中文乱码// \r 表示:回车符(ACSII:13 或0x0d),就是我们常说的硬回车。 \n 表示:换行(ACSII:10 或0x0a),就是我们常说的软回车。message.writeUTFBytes(msg+"\r\n");// \r\n是输出的HTML代码换行,客户看到的效果没有换行socket.writeBytes(message);//写入Socket的缓冲区socket.flush();//调用flush方法发送信息myText.text+=msg+"\r\n";//在客户端屏幕上输出发送的内容myInput.text="";//清空发言框}]]></mx:Script><mx:TextArea x="10" y="10" width="703" height="263" id="myText"/><mx:TextInput x="10" y="297" width="605" id="myInput"/>?? ?<mx:Button x="648" y="297" label="发送" id="myBtn" click="sendMessage(myInput.text)"/></mx:Application>
Java端:package f1.f1_005.socket;
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;
public class Server2 {private BufferedReader reader; //负责输入private ServerSocket server;//服务器套接字private Socket socket;public Server2(){} //缺省构造函数void StartServer(){ //启动服务器try {server = new ServerSocket(8888); //创建服务器套接字System.out.println("服务器套接字建立完毕");while(true){System.out.println("等待客户机");socket = server.accept();//若客户机提出连接请求,与socket连接System.out.println("完成与客户机的连接");//获取socket输入流,“utf-8”这个编码设置是为了更好显示中文reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));getMessage();//读取来自客户机的数据,并输出至画面上}} catch (IOException e) {System.out.println(e);e.printStackTrace();}}void getMessage(){ //读取来自套接字的信息try {while(true){ //循环String msg = reader.readLine();if(msg == null){break;}System.out.println("客户机:"+msg);}} catch (IOException e) {e.printStackTrace();} finally {try {System.out.println("客户机中断连接");if(reader!=null) reader.close();if(socket!=null) socket.close();reader = null;socket = null;} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {Server2 s2 = new Server2();s2.StartServer();}
}-------------------------------------------------------
实例三:Flex 端:<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="353" height="336"creationComplete="initApp();" ><mx:Script><![CDATA[import mx.utils.ObjectUtil;/* ?ByteArrayClass public class ByteArray?继承 ByteArray --> ?Object?Implements IDataInput, IDataOutput?Subclasses ByteArrayAsset?
属性:bytesAvailable : uint ?[] 可从字节数组的当前位置到数组末尾读取的数据的字节数。defaultObjectEncoding : uint[] 指示用于新 ByteArray 实例的 ByteArray 类的默认对象编码。length : uintByteArray 对象的长度(以字节为单位)。position : uint 将文件指针的当前位置(以字节为单位)移动或返回到 ByteArray 对象中。
方法:ByteArray()创建一个表示填充的字节数组的 ByteArray 实例,以便使用此类中的方法和属性来优化数据存储和数据流。writeUTF(value:String):void将 UTF-8 字符串写入字节流。writeUTFBytes(value:String):void 将 UTF-8 字符串写入字节流。writeByte(value:int):void 在字节流中写入一个字节。writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void ?将指定字节数组 bytes(起始偏移量为 bytes,从 0 开始的索引)中包含 length 个字节的字节序列写入字节流。offset:uint (default = 0) — 从 0 开始的索引,表示在数组中开始写入的位置。SocketClass public class Socket?继承 Socket ?EventDispatcher ?Object?Implements IDataInput, IDataOutput?类使 代码可以建立套接字连接并读取和写入原始二进制数据。它与 XMLSocket 类似,但没有指定接收或传输的数据格式。属性:bytesAvailable : uint[] 输入缓冲区中可读取的数据的字节数。connected : Boolean[] 指示此 Socket 对象目前是否已连接。objectEncoding : uint在写入或读取对象时,控制所使用的 AMF 的版本。方法:Socket(host:String = null, port:int = 0)创建一个 Socket 对象。close():void关闭套接字。 Socket?connect(host:String, port:int):void将套接字连接到指定的主机和端口。 Socket?dispatchEvent(event:Event):Boolean将事件调度到事件流中。 EventDispatcher?flush():void对套接字输出缓冲区中积累的所有数据进行刷新。?readByte():int从套接字读取一个带符号字节。 Socket? ? ?readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void从套接字读取 length 参数所指定的数据的字节数。?readMultiByte(length:uint, charSet:String):String使用指定的字符集,从该字节流读取一个多字节字符串。 readUnsignedByte():uint从套接字读取一个无符号字节。 Socket? ? ?readUnsignedInt():uint从套接字读取一个无符号的 32 位整数。 Socket? ? ?readUnsignedShort():uint从套接字读取一个无符号的 16 位整数。?readUTF():String从套接字读取一个 UTF-8 字符串。 Socket? ? ?readUTFBytes(length:uint):String从套接字读取 length 参数所指定的 UTF-8 数据的字节数,并返回一个字符串。? writeByte(value:int):void将一个字节写入套接字。 Socket? ? ?writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void从指定的字节数组写入一系列字节。? writeMultiByte(value:String, charSet:String):void使用指定的字符集,从该字节流写入一个多字节字符串。 Socket? ? ?writeObject(object:*):void以 AMF 序列化格式将一个对象写入套接字。 Socket? ? ?writeShort(value:int):void将一个 16 位整数写入套接字。 Socket? ? ?writeUnsignedInt(value:uint):void将一个无符号的 32 位整数写入套接字。 Socket? ? ?writeUTF(value:String):void将以下数据写入套接字:一个无符号 16 位整数,它指示了指定 UTF-8 字符串的长度(以字节为单位),后面跟随字符串本身。 Socket? ? ?writeUTFBytes(value:String):void将一个 UTF-8 字符串写入套接字。?
事件: Event.XXclose 在服务器关闭套接字连接时调度。 Socket? ? ?connect 在建立网络连接后调度。 Socket? ? deactivate Flash Player 或 AIR 应用程序失去操作系统焦点并变为非活动状态时调度。 EventDispatcher? ? ?ioError 在出现输入/输出错误并导致发送或加载操作失败时调度。 Socket? ? ?securityError 若对 Socket.connect() 的调用尝试连接到调用方安全沙箱外部的服务器或端口号低于 1024 的端口,则进行调度。 Socket? ? ?socketData 在套接字接收到数据后调度。?
*/private var socket:Socket = new Socket();private var intClient:int;//定义客户端数字出拳private var intServer:int;//定义服务端数字出拳private var intSY:int;//定义输赢判断private var strClient:String;//客户端文字出拳private var strServer:String;//服务端的文字出拳internal function initApp():void{socket.connect("127.0.0.1",8888);socket.addEventListener(Event.CONNECT,funConnect);?? ? ? ? ? ? ? ?socket.addEventListener(Event.CLOSE,funClose);?? ? ? ? ? ? ? ?socket.addEventListener(ProgressEvent.SOCKET_DATA,funSocket);}internal function funConnect(e:Event):void{myText.text+="连接已建立 \n";}internal function funClose(e:Event):void{myText.text+="连接已关闭 \n";}private function sendMessage(msg:String):void{var message:ByteArray = new ByteArray();message.writeUTF(msg);//发送出拳数字socket.writeBytes(message);socket.flush();intClient=int(msg);switch(intClient){//将数字转换成文字用于发布到屏幕上case 0:?? ? ? ? ? ? ? ? ? ? ? ? ? ?strClient="剪刀";?? ? ? ? ? ? ? ? ? ? ? ? ? ?break;?? ? ? ? ? ? ? ? ? ?case 1:?? ? ? ? ? ? ? ? ? ? ? ? ? ?strClient="锤";?? ? ? ? ? ? ? ? ? ? ? ? ? ?break;?? ? ? ? ? ? ? ? ? ?case 2:?? ? ? ? ? ? ? ? ? ? ? ? ? ?strClient="包袱";?? ? ? ? ? ? ? ? ? ? ? ? ? ?break;}myText.text+="你出:"+strClient+"; ?";?? ? ? ? ? ? ? ?myInput.text="";}internal function funSocket(e:ProgressEvent):void{//接到服务器信息var msg:String="";while(socket.bytesAvailable){msg=socket.readUTF();intServer=int(msg);intSY=intClient-intServer;//通过数值判断输赢switch(intServer)//将数字转换成文字用于发布到屏幕上?? ? ? ? ? ? ? ? ? ?{?? ? ? ? ? ? ? ? ? ? ? ?case 0:?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?strServer="剪刀";?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;?? ? ? ? ? ? ? ? ? ? ? ?case 1:?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?strServer="锤";?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;?? ? ? ? ? ? ? ? ? ? ? ?case 2:?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?strServer="包袱";?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;?? ? ? ? ? ? ? ? ? ?}?? ? ? ? ? ? ? ? ? ?myText.text+="服务器出:"+strServer+"; ?";?? ? ? ? ? ? ? ? ? ?//判断输赢的算法?? ? ? ? ? ? ? ? ? ?if(intSY>0&&intSY<2)?? ? ? ? ? ? ? ? ? ?{?? ? ? ? ? ? ? ? ? ? ? ? ? ?myText.text+=" 结果:你赢了 \n";?? ? ? ? ? ? ? ? ? ?}else if(intClient==intServer)?? ? ? ? ? ? ? ? ? ?{?? ? ? ? ? ? ? ? ? ? ? ? ? ?myText.text+=" 结果:平手 \n";?? ? ? ? ? ? ? ? ? ?}else if(intSY<0&&intSY>-2)?? ? ? ? ? ? ? ? ? ?{?? ? ? ? ? ? ? ? ? ? ? ? ? ?myText.text+=" 结果:你输了 \n";?? ? ? ? ? ? ? ? ? ?}else if(intSY>=2)?? ? ? ? ? ? ? ? ? ?{?? ? ? ? ? ? ? ? ? ? ? ? ? ?myText.text+=" 结果:你输了 \n";?? ? ? ? ? ? ? ? ? ?}else if(intSY<=-2)?? ? ? ? ? ? ? ? ? ?{?? ? ? ? ? ? ? ? ? ? ? ? ? ?myText.text+=" 结果:你赢了 \n";?? ? ? ? ? ? ? ? ? ?}?? ? ? ? ? ? ? ? ? ?// myText滚动到最下面?? ? ? ? ? ? ? ? ? ?myText.verticalScrollPosition = myText.maxVerticalScrollPosition;}}]]></mx:Script><mx:TextArea x="10" y="32" width="331" height="263" id="myText"/>?? ?<mx:TextInput x="10" y="303" width="245" id="myInput"/>?? ?<mx:Button x="273" y="304" label="发送" id="myBtn" click="sendMessage(myInput.text)"/>?? ?<mx:Label x="10" y="10" text="规则:0代表剪刀;1代表锤;2代表包袱" width="331" fontWeight="bold"/></mx:Application>
Java 端:package f1.f1_005.socket;
import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.Random;import java.util.Vector;
/**知识点:套接字管理器(Vector)会将于客户机连接的套接字添加到其列表中,在客户机断开连接后,在将相应的套接自从列表中删除,从中可以看出,客户机连接数与列表中添加套接字数目是一致的。Vector sManager=new Vector();sManager.add(socket); ?// 向列表添加套接字sManager.remove(socket); //从列表移除套接字sManager.size(); //获取客户机连接数*/public class Server3 {private ServerSocket server;//Vector 类提供了实现可增长数组的功能,随着更多元素加入其中,数组变的更大。Vector sManager = new Vector();//管理套接字的VectorRandom rnd = new Random();//创建随机数的发生器public Server3(){}void startServer()//运行服务器{try {server = new ServerSocket(8888);System.out.println("服务器套接字已创建成功!");while (true){Socket socket = server.accept();System.out.println("已经与客户机连接");new KBBCom_Thread(socket).start();sManager.add(socket);System.out.println("当前客户机连结数:"+sManager.size());}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {Server3 server=new Server3();?? ? ? ?server.startServer();}class KBBCom_Thread extends Thread ?//与客户机进行通信的线程累{Socket socket;//套接字引用变量private DataInputStream reader;//套接字输入流private DataOutputStream writer;KBBCom_Thread(Socket socket){ //构造函数this.socket = socket;}public void run(){try {//获取套接字的输入输出流reader = new DataInputStream(socket.getInputStream());writer = new DataOutputStream(socket.getOutputStream());String msg;//如果收到客户端发来的数据while((msg=reader.readUTF())!= null){//向客户机传送0-2之间的整型随机数writer.writeUTF(rnd.nextInt(3)+"\n");writer.flush();System.out.println("来自客户机:"+msg);}} catch (IOException e) {e.printStackTrace();} finally {try {sManager.remove(socket);//删除套接字//关闭输入输出流及套接字if(reader!=null)reader.close();if(writer!=null)writer.close();if(socket!=null)socket.close();reader=null;writer=null;socket=null;//向屏幕输出相关信息System.out.println("客户机离开");?? ? ? ? ? ? ? ? ? ?System.out.println("当前客户机的连接数:"+sManager.size());} catch (IOException e) {e.printStackTrace();}}}}
}
-------------------------------------------------------
实例四:Flex 端:<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"creationComplete="initApp();" width="369" height="326"><mx:Script><![CDATA[private var socket:Socket = new Socket();internal function initApp():void{socket.connect("192.168.0.56",8888);//执行连接//localhost==127.0.0.1?? ? ? ? ? ? ? ?//监听连接成功事件?? ? ? ? ? ? ? ?socket.addEventListener(Event.CONNECT,funConnect);?? ? ? ? ? ? ? ?//监听关闭事件?? ? ? ? ? ? ? ?socket.addEventListener(Event.CLOSE,funClose);?? ? ? ? ? ? ? ?//监听服务器新信息?? ? ? ? ? ? ? ?socket.addEventListener(ProgressEvent.SOCKET_DATA,funSocket);}internal function funConnect(e:Event):void{myText.text+="连接已建立 \n";}internal function funClose(e:Event):void{myText.text+="连接已关闭 \n";}internal function sendMessage(msg:String):void{//新建一个ByteArray来存放数据?? ? ? ? ? ?var message:ByteArray=new ByteArray();?? ? ? ? ? ?//写入数据,使用writeUTFBytes以utf8格式传数据,避免中文乱码?? ? ? ? ? ?message.writeUTFBytes(msg+"\n");?? ? ? ? ? ?//写入socket的缓冲区?? ? ? ? ? ?socket.writeBytes(message);?? ? ? ? ? ?//调用flush方法发送信息?? ? ? ? ? ?socket.flush();?? ? ? ? ? ?//清空消息框?? ? ? ? ? ? ? ?myInput.text="";}internal function funSocket(e:Event):void{var msg:String="";?? ? ? ? ? ?//循环读取数据,socket的bytesAvailable对象存放了服务器传来的所有数据?? ? ? ? ? ?while(socket.bytesAvailable)?? ? ? ? ? ?{?? ? ? ? ? ?//强制使用utf8格式,避免中文乱码?? ? ? ? ? ?msg += socket.readMultiByte(socket.bytesAvailable,"utf8"); //UTF-8?? ? ? ? ? ?//使用\n换行符号把信息切开?? ? ? ? ? ?var arr:Array = msg.split("\n");?? ? ? ? ? ?for(var i:int=0;i<arr.length;i++)?? ? ? ? ? ?{?? ? ? ? ? ?if(arr[i].length > 0){?? ? ? ? ? ?//正则表达式,回车符?? ? ? ? ? ?var myPattern:RegExp=/\r/;?? ? ? ? ? ?//删除回车符?? ? ? ? ? ?arr[i] = arr[i].replace(myPattern,"");?? ? ? ? ? ?//在聊天框中输出?? ? ? ? ? ?myText.text+=arr[i]+"\n";?? ? ? ? ? ?}?? ? ? ? ? ?}?? ? ? ? ? ?myText.horizontalScrollPosition = myText.maxVerticalScrollPosition;//滚动到最下面?? ? ? ? ? ?}}]]></mx:Script><mx:TextInput x="10" y="10" width="344" text="名字" id="myName"/><mx:TextArea x="10" y="42" width="344" height="247" id="myText"/>?? ?<mx:TextInput x="10" y="297" width="270" id="myInput"/>?? ?<mx:Button x="288" y="298" label="发送" id="myBtn" click="sendMessage(myName.text+':'+myInput.text)"/></mx:Application>
Java 端:package f1.f1_005.socket;
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.Vector;
public class Server4 {
private ServerSocket server;private BManager bMan=new BManager(); ?//消息广播public Server4() {}void startServer() ?//启动服务器{try {server=new ServerSocket(8888); //创建服务器套接字System.out.println("服务器套接字建立完毕");while(true)?? ? ? ? ? ?{Socket socket=server.accept();//若客户机提请求,socket连接new Chat_Thread(socket).start();//启动线程bMan.add(socket);//添加套接字bMan.sendClientInfo();//使用套接字输出当前聊天人数?? ? ? ? ? ?}} catch (IOException e) {System.out.println(e);e.printStackTrace();}}class Chat_Thread extends Thread{//与客户机进行通信的线程累Socket socket;//套接字引用变量private BufferedReader reader;//引用套接字输入流;private PrintWriter writer;//引用套接字输出流;Chat_Thread(Socket socket){//构造函数this.socket = socket;}public void run() {try {reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf8"));//utf8UTF-8//PrintWriter 的第二个参数:autoFlush - A boolean; if true, the println, printf, or format methods will flush the output bufferwriter = new PrintWriter(socket.getOutputStream(),true);String msg;//从输出流获取信息while((msg=reader.readLine()) != null){System.out.println(msg);?? ? ? ? ? ? ? ? ? ?//向所有客户机传送信息bMan.sendToAll(msg);}} catch (IOException e) {e.printStackTrace();} finally {try {//从消息广播者立标中删除socketbMan.remove(socket);if(reader!=null)reader.close();if(writer!=null)writer.close();if(socket!=null)socket.close();reader=null;writer=null;socket=null;System.out.println("客户机离开");//向所有客户机传送当前连接数?? ? ? ? ? ? ? ? ? ?bMan.sendClientInfo();} catch (IOException e) {e.printStackTrace();}}}}public static void main(String[] args) {Server4 server=new Server4();?? ? ? ?server.startServer();}
}
//消息广播者类,继承Vector类class BManager extends Vector{ //消息广播者类,继承Vector类BManager (){}//构造函数
void add(Socket socket) {super.add(socket); //添加套接字}
void remove(Socket socket) {super.remove(socket);//删除套接字}//向所有客户机传送消息,同步化方法。synchronized void sendToAll(String msg) {PrintWriter writer = null;//输出流Socket socket;for (int i = 0; i < size(); i++) {socket = (Socket)elementAt(i);try {//获取第i个套接字输出流writer = new PrintWriter(socket.getOutputStream(),true); ?//就是因为掉了个ture ,客服端就显示不了数据} catch (IOException e) {e.printStackTrace();}//使用第i各套接字输出流,输出消息if(writer!=null) ?writer.println(msg);}}//向所有客户机发送当前聊天人数synchronized void sendClientInfo(){String info = "当前聊天人数:"+size();System.out.println(info);?? ? ? ?sendToAll(info);}}
-------------------------------------------------------
实例五:Flex 端:<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12"?creationComplete="initApp()" width="547" height="326" ><mx:Script><![CDATA[import mx.controls.Alert;import com.flex.f018.MyLogin;import flash.net.Socket;import flash.utils.ByteArray;import mx.managers.PopUpManager;import flash.events.MouseEvent;private var strPD:String="22--";//协议头判断private var socket:Socket=new Socket();private var win:MyLogin=new MyLogin();internal function initApp():void{win.width=240;win.height=94;win.x=153;win.y=116;PopUpManager.addPopUp(win,this,true);win.myBtn.addEventListener(MouseEvent.CLICK,funBtn);//socket.connect("127.0.0.1",8888);//socket.addEventListener(ProgressEvent.SOCKET_DATA,funSocket);}internal function funChoose(event:MouseEvent):void{var item:Object=myList.selectedItem;strPD="33--"+item+"--";}internal function funBtn(event:MouseEvent):void{myName.text=win.txtName.text;PopUpManager.removePopUp(win);socket.connect("127.0.0.1",8888);socket.addEventListener(Event.CONNECT,funConnect);//监听关闭事件socket.addEventListener(Event.CLOSE,funClose);socket.addEventListener(ProgressEvent.SOCKET_DATA,funSocket);myList.addEventListener(MouseEvent.CLICK,funChoose);sendMessage("11"+myName.text);
}
internal function funConnect(event:Event):void{trace("[log] funConnect:连接已建立");myText.text+="连接已建立 \n";//sendMessage("11"+myName.text);}internal function funClose(e:Event):void{trace("[log] funClose:连接已关闭");myText.text+="连接已关闭 \n";}internal function sendMessage(msg:String):void{trace("[log] sendMessage :" + msg);var message:ByteArray=new ByteArray();message.writeUTFBytes(msg+"\n");socket.writeBytes(message);socket.flush();myInput.text="";}internal function funSocket(event:ProgressEvent):void{trace("[log] funSocket ");var msg:String="";var pd:String=""; //协议判断字符var intCD:int=0;while(socket.bytesAvailable){msg=socket.readMultiByte(socket.bytesAvailable,"utf8");trace("[log] funSocket msg:"+msg);pd=msg.substring(0,2);intCD=msg.length;//获取字符串长度if(pd=="11") // 11--UserName{// 11开头表示更新用户列表msg=msg.substring(4,intCD);var myPattern2:RegExp=/\r\n/;//清除回车和换行符//var myPattern3:RegExp=/\n/;msg=msg.replace(myPattern2,'');//msg=msg.replace(myPattern3,'');var arrList:Array=msg.split("--");arrList.unshift("所有人");trace("[log] 11 arrList : " +arrList);myList.dataProvider=arrList;}else if(pd=="22") // 22UserNamed登录了{msg=msg.substring(2,intCD);var arr:Array=msg.split('\n');for(var i:int=0;i<arr.length;i++){if(arr[i].length>1){var myPattern:RegExp=/\r/;arr[i]=arr[i].replace(myPattern,'');myText.text+=arr[i]+"\n";}}myText.verticalScrollPosition = myText.maxVerticalScrollPosition;//滚动到最下面}else if(pd=="33"){}else if(pd=="44")// 44当前在线认识:Size人{msg=msg.substring(2,intCD);labCount.text=msg;}else{}}}]]></mx:Script><mx:TextArea x="10" y="10" width="344" height="279" id="myText"/><mx:TextInput x="103" y="297" width="357" id="myInput"/><mx:Button x="468" y="298" label="发送" id="myBtn" click="sendMessage(strPD+myName.text+'--'+myInput.text)"/><mx:Label x="10" y="299" width="85" textAlign="right" id="myName" fontWeight="bold" color="#ffffff"/><mx:List x="367" y="42" height="247" id="myList" width="170"></mx:List><mx:Label x="367" y="13" width="170" id="labCount"/></mx:Application>
Java 端:package f1.f1_005.socket;
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.*;
/** 自定义的协议 * 收到消息: 11开头表示新加入了聊天用户;22开头表示公聊;33开头表示私聊* 发送消息:11开头表示更新用户列表;22开头表示发送到屏幕上;44发送在线人数*?*/public class Server5 {private ServerSocket server;private BManager5 bMan = new BManager5(); //消息广播者//Map接口的HashMap类,元素拥有固定key值,key值不重复,这里用来存放在线用户Map<Socket, String> clientList = new HashMap<Socket, String>();public Server5(){}//构造函数public void startServer(){ //启动服务器try {server = new ServerSocket(8888); //创建服务器套接字System.out.println("服务器套接字建立完毕");while(true){Socket socket = server.accept();//若客户机提出请求,使用socket进行连接//String strIP = socket.getInetAddress().toString();//登陆者的ipnew Chat_Thread(socket).start();//启动线程bMan.add(socket);//添加套接字bMan.sendClientInfo();//使用套接字输出当前聊天人数//funList(clientList);//bMan.sendToAll(strIP+"/加入聊天室");}} catch (IOException e) {System.out.println(e);e.printStackTrace();}}class Chat_Thread extends Thread{ //与客户机进行通讯的线程类private Socket socket;//x1private BufferedReader reader;//套接字输入流;private PrintWriter writer;//套接字输出流Chat_Thread(Socket socket){this.socket = socket;//this.socket就是x1处的socket}public void run(){try {reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf8"));//PrintWriter 的第二个参数:autoFlush - A boolean; if true, the println, printf, or format methods will flush the output bufferwriter=new PrintWriter(socket.getOutputStream(),true);String msg;//msg获取消息// while 这样写,在关闭浏览器的时候,会进入finally ?while((msg=reader.readLine())!=null) //while(true){{//if((msg=reader.readLine())!=null){System.out.println(msg);//服务器屏幕输出消息String str = msg.substring(0,2);//截取前两个个字符int a=Integer.parseInt(str);//强制转换成intString[] arrMsg=msg.split("--");//将获取的消息以"--"符号为标志分解成数组switch(a){case 11://当消息以11开头的时候,将登陆者的信息储存到hashmap之中,并向客户端发送新的在线列表String strName = msg.substring(2);//获取登陆者名字,消息格式“11eko”System.out.println(strName+"登陆了");//服务器屏幕输出谁登陆了bMan.sendToAll("22"+strName+"登陆了");//广播谁登陆了clientList.put(this.socket,strName);//加入到HashMap中funList(clientList);//广播在线列表break;case 22://当消息以22开头的时候,表示公聊,内容为“22--eko--内容”System.out.println("公聊");//构造消息,arrMsg[0]=消息头,arrMsg[1]消息发送者,arrMsg[2]消息内容msg=arrMsg[0]+arrMsg[1]+"说:"+arrMsg[2];bMan.sendToAll(msg);break;case 33://消息以33开头时候,内容为“33--sandal--eko--内容”//arrMsg[1]为说话对象,arrMsg[2]为说话人,arrMsg[3]为消息内容if(arrMsg[1].equals("所有人"))//当说话对象为"所有人"的时候{//构造消息"22eko说:内容"msg="22"+arrMsg[2]+"说:"+arrMsg[3];//向所有人发送消息bMan.sendToAll(msg);}else//其他情况就是向具体的某个人发送消息了{Socket socketOne=new Socket();System.out.println("私聊");Set set = clientList.keySet();//使用keySet方法获取所有key值Iterator it = set.iterator();//使用Iterator(迭代器)来遍历数据while (it.hasNext()) {//返回是否还有没被访问过的对象Object ok=it.next();//返回下一个没被访问过的对象Object ov=clientList.get(ok);//get方法返回拥有key的元素if(ov.equals(arrMsg[1]))//如果在client中找到"消息发给谁"的时候,发给对方??????{socketOne=(Socket)ok;//强制转换成key值类型;bMan.sendToONE(socketOne,"22(悄悄话)"+arrMsg[2]+"对你说:"+arrMsg[3]);}else if(ov.equals(arrMsg[2]))//如果在client中找到"发消息的人"的时候,发给他自己???????{socketOne=(Socket)ok;bMan.sendToONE(socketOne,"22(悄悄话)你对"+arrMsg[1]+"说:"+arrMsg[3]);}}}break;}//}}} catch (IOException e) {e.printStackTrace();} finally {try {if(clientList.containsKey(socket)){bMan.sendToAll("22"+clientList.get(socket)+"离开了...");//广播消息,谁离开了clientList.remove(socket);//删除socketfunList(clientList);//广播在线列表}bMan.remove(socket);if(reader !=null) reader.close();if(writer !=null) writer.close();if(socket !=null) socket.close();reader=null;writer=null;socket=null;System.out.println("客户机离开");bMan.sendClientInfo();//广播在线人数} catch (Exception e) {}}}void funList(Map clientList)// 广播在线列表???????б?{String strList = "";//在线列表Set set = clientList.keySet();//使用keySet方法获取所有key值System.out.println(set);Iterator it = set.iterator();//使用Iterator(迭代器)来遍历数据System.out.println(it);while (it.hasNext()) {//把用户名称发给在线所有客户端 strList+="--";strList+=clientList.get(it.next());}bMan.sendToAll("11"+strList);}}
public static void main(String[] args){Server5 server = new Server5();server.startServer();}}
class BManager5 extends Vector{BManager5(){}void add(Socket socket){?super.add(socket);}void remove(Socket socket){super.remove(socket);}synchronized void sendToAll(String msg){//给所有人广播函数PrintWriter writer = null ;Socket socket;for (int i = 0; i < size(); i++) {//执行循环socket = (Socket)elementAt(i);//获取第i个套接字try {//获取第i个套接字输出流writer = new PrintWriter(socket.getOutputStream(),true);} catch (IOException e) { }System.out.println(msg);//使用第i各套接字输出流,输出消息if(writer!=null)writer.println(msg);}}synchronized void sendToONE(Socket socket,String msg){//私聊函数PrintWriter writer=null;Socket sock;for(int i=0;i<size();i++){sock = (Socket)elementAt(i);if(sock == socket){//与给所有人广播函数类似,仅加入了判断,只有当socket管理器中的socket等于传入的socket的时候才发送消息try{writer=new PrintWriter(sock.getOutputStream(),true);}catch(Exception ie){}if(writer!=null)writer.println(msg);}}}synchronized void sendClientInfo(){int a = size();String msg ="44当前在线人数:" +a+"人";sendToAll(msg);}}
-------------------------------------------------------
1 楼 泸洲墨墨 2012-05-27 博主,我爱死你了,太谢谢了
来,波一个
实在是感谢啊,我找了好久了,拜谢!!!!!!!