java服务端代码:两个类【ChatServer.java 】【ChatThread.java】
ChatServer作用是监听客户端连接请求,如果有新socket连接,生成一个新的线程以应对本次socket连接。
ChatThread作用是:与某一客户端socket绑定,监听客户端发送的信息,然后将收到的信息“广播”到其他所有客户端。
【原创】
package sockettest; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.LinkedList; import java.util.List; public class ChatServer { //公共聊天室 public static void main(String[] args) throws IOException { ServerSocket ss=new ServerSocket(6666); List<Socket> socketList=new LinkedList<Socket>(); while(true){ Socket socket=ss.accept(); socketList.add(socket); Thread t=new Thread(new ChatThread(socket,socketList)); t.start(); } } }
package sockettest; import java.io.*; import java.net.*; import java.util.List; public class ChatThread implements Runnable{ private static String xml = "<?xml version=\"1.0\"?><cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0"; private List<Socket> socketList; private Socket socket; private BufferedReader bufferedReader; public ChatThread(Socket socket,List<Socket> socketList){ this.socket=socket; this.socketList=socketList; } private void preRun(){ PrintWriter pw=this.getSocketPrintWriter(socket); pw.println(xml); pw.flush(); InputStreamReader r=null; try { r = new InputStreamReader(this.socket.getInputStream(),"UTF-8"); this.bufferedReader=new BufferedReader(r); } catch (IOException e) { e.printStackTrace(); } } private PrintWriter getSocketPrintWriter(Socket socket){ OutputStream os=null; try { os = socket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } OutputStreamWriter osw=new OutputStreamWriter(os); BufferedWriter bw=new BufferedWriter(osw); return new PrintWriter(bw, true); } private void broadcast(String msg){ for(Socket s:socketList){ PrintWriter pw=this.getSocketPrintWriter(s); pw.println(msg); } } public void run() { String msg=""; this.preRun(); while(true){ try { msg="from client "+this.bufferedReader.readLine(); this.broadcast(msg); } catch (IOException e) { try { this.bufferedReader.close(); this.socket.close(); this.socketList.remove(this.socket); this.broadcast("somebody exist....people size :" +socketList.size()); } catch (IOException e1) { e1.printStackTrace(); } e.printStackTrace(); return ; } } } }
Flex客户端代码:【ChatClientDemo.mxml】【LoginWnd.mxml】【GlobalMasage.as 】
Flsha Builder 4.5
ChatClientDemo.mxml 聊天注界面,实现socket通信
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" creationComplete="application1_creationCompleteHandler(event)"> <fx:Style source="ChatClientDemo.css"/> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <fx:Script> <![CDATA[ import mx.events.FlexEvent; import mx.managers.PopUpManager; import mx.messaging.channels.StreamingAMFChannel; private var loginWnd:LoginWnd=new LoginWnd(); private var socket:Socket=new Socket(); protected function application1_creationCompleteHandler(event:FlexEvent):void { PopUpManager.addPopUp(loginWnd,this,true); PopUpManager.centerPopUp(loginWnd); } protected function btnConn_clickHandler(event:MouseEvent):void { socket.connect(GlobalMasage.SERVER_HOST,GlobalMasage.SERVER_PORT); socket.addEventListener(Event.CONNECT,event_connHandler); socket.addEventListener(ProgressEvent.SOCKET_DATA,event_receiveFromServerHandler); socket.addEventListener(Event.CLOSE,event_closeHandler); } protected function btnSend_clickHandler(event:MouseEvent):void { var msg:ByteArray=new ByteArray(); msg.writeUTFBytes(GlobalMasage.loginName+":"+txtInput.text+"\n"); socket.writeBytes(msg); socket.flush(); this.txtInput.text=""; } private function event_closeHandler(event:Event):void{ } private function event_connHandler(event:Event):void{ this.txtContainer.text+="-----------服务器链接成功---------\n"; } private function event_receiveFromServerHandler(event:ProgressEvent):void { var msg:String=null; msg=socket.readMultiByte(socket.bytesAvailable,"utf8"); this.txtContainer.text+=msg+"\n"; } protected function btnClearScreen_clickHandler(event:MouseEvent):void { this.txtContainer.text=""; } ]]> </fx:Script> <s:TextArea id="txtContainer" x="64" y="16" width="480" height="277"/> <s:TextInput id="txtInput" x="64" y="326" width="480"/> <s:Button id="btnConn" x="552" y="16" label="连接" click="btnConn_clickHandler(event)"/> <s:Button id="btnClearScreen" x="552" y="62" label="清屏" click="btnClearScreen_clickHandler(event)"/> <s:Button x="552" y="118" label="断开"/> <s:Button id="btnSend" x="552" y="327" label="发送" click="btnSend_clickHandler(event)"/> </s:Application>
LoginWnd.mxml 用于用户登录,输入一个用户名,无需注册
<?xml version="1.0" encoding="utf-8"?> <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300"> <fx:Script> <![CDATA[ import mx.managers.PopUpManager; protected function btnLogin_clickHandler(event:MouseEvent):void { // TODO Auto-generated method stub GlobalMasage.loginName=txtLoginName.text; PopUpManager.removePopUp(this); } ]]> </fx:Script> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <s:Panel x="0" y="0" width="400" height="300"> <s:Label x="81" y="99" width="48" height="19" fontSize="15" text="名字"/> <s:TextInput id="txtLoginName" x="145" y="95"/> <s:Button id="btnLogin" x="145" y="154" label="登录" click="btnLogin_clickHandler(event)"/> </s:Panel> </s:Group>
l
GlobalMasage.as :只是用来存储全局变量
package { [Bindable] public class GlobalMasage { public function GlobalMasage() { } public static var SERVER_HOST:String="127.0.0.1"; public static var SERVER_PORT:Number=6666; public static var loginName:String; } }