一、準(zhǔn)備:
服務(wù)端:JDK1.5 (這個(gè)不用介紹了吧?)
服務(wù)端IDE:eclipse ( 它的主頁(yè) )
客戶端:FLEX 3 (Adobe® Flex® 3 是用于構(gòu)建和維護(hù)在所有主要瀏覽器、桌面和操作系統(tǒng)一致地部署的極具表現(xiàn)力的 Web 應(yīng)用 程序 的高效率的開(kāi)放 源碼 框架 。)
客戶端IDE:Flex Builder 3 ( 它的官方摘要頁(yè) )
二、緣分的相遇(建立連接):
既然是通信,當(dāng)然第一步就是要建立連接啦。我們還是用最簡(jiǎn)單的看代碼的方式來(lái)開(kāi)始我們的連接。
==========================================
==服務(wù)端代碼:Jserver1.java
==========================================
import java.net.*; import java.io.*; public class Jserver1 { public static void main(String[] args) { ServerSocket server=null; try{ ??server=new ServerSocket(719);//在端口719建立一個(gè)服務(wù)器套接字對(duì)象 ??System.out.println("服務(wù)端等待"); ??while(true){ ? ?System.out.println("等待客戶機(jī)"); ? ?Socket newSocket=server.accept();//客戶端向我們建立的服務(wù)器套接字發(fā)送連接請(qǐng)求,則向下執(zhí)行 ? ?System.out.println("已與客戶機(jī)連接"); ??} }catch(IOException ie) { ??System.out.println(ie); }finally{ ??try ??{ ? ?if(server!=null) server.close();//關(guān)閉服務(wù)器套接字。為什么要用finally關(guān)鍵字來(lái)做這個(gè)事呢?HOHO thinking in java里大師已經(jīng)說(shuō)得很清楚了,就是無(wú)論出現(xiàn)什么異常,都保證我們的服務(wù)端套接字能被關(guān)閉。 ??}catch(IOException ie){} } }
?嘎嘎,怎么樣 注釋寫(xiě)得夠清楚了吧?OK 讓我們編譯
運(yùn)行
,得到的結(jié)果應(yīng)該如圖:
OK 再讓我們來(lái)看看客戶端的代碼是怎么樣的:
==========================================
==客戶端代碼:Jclient1.
m
xml
===================================================
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creati f width="349" height="326"> <mx:Script> ??<![CDATA[ ??import flash.net.Socket; ??private var socket:Socket; ??internal function initApp():void ??{ ? ?socket=new Socket();//創(chuàng)建Socket對(duì)象 ? ?socket.connect("localhost",719); //連接服務(wù)器 ? ?socket.addEventListener(Event.CONNECT,connectFun);//監(jiān)聽(tīng)是否連接上服務(wù)器 ? ?socket.addEventListener(Event.CLOSE,closeFun);//監(jiān)聽(tīng)套接字連接是否關(guān)閉 ? ? ??} ??private function connectFun(event:Event):void ??{ ? ?jText.text+="已經(jīng)成功連接到服務(wù)器!\n"; ??} ??private function closeFun(event:Event):void ??{ ? ?jText.text+="和服務(wù)器斷開(kāi)!\n" ??} ??]]> </mx:Script> <mx:TextArea x="10" y="10" width="327" height="309" id="jText"/> </mx:Application>
?界面非常簡(jiǎn)單啦,其實(shí)就是一個(gè)TextArea來(lái)顯示連接的結(jié)果而已,運(yùn)行的結(jié)果如下圖(注意,服務(wù)端也應(yīng)該在運(yùn)行!):
在as3.0中,所有和網(wǎng)絡(luò)通信有關(guān)的類(lèi)都位于flash.net包中,這里使用的是Socket類(lèi)對(duì)象。
==========================================
==我們來(lái)詳細(xì)說(shuō)明一下上面用到的Socket類(lèi):
==========================================
Socket對(duì)象的常用創(chuàng)建方法有下面2種:
var socket:Socket=new Socket();//例一
?或者
var socket:Socket=new Socket("localhost",719);//例二.這條語(yǔ)句設(shè)置了服務(wù)器地址為localhost 端口是719
?當(dāng)指定了了服務(wù)器地址和端口,Socket對(duì)象將自動(dòng)開(kāi)始連接服務(wù)器。如果不指定,則需要條用connect方法才開(kāi)始執(zhí)行連接動(dòng)作,意思就是,例二的代碼和下面的代碼是等效的:
var socket:Socket=new Socket(); socket.connect("localhost",719);
?完成連接動(dòng)作后,接下來(lái)要獲取服務(wù)端得返回信息。
Socket對(duì)象和URLLOADER啊之類(lèi)的對(duì)象都是一樣,利用事件機(jī)制來(lái)處理服務(wù)器端的信息,我們只要給Socket對(duì)象添加相關(guān)的事件監(jiān)聽(tīng)
函數(shù)
就可以捕捉到服務(wù)器端的信息,Socket對(duì)象的事件主要有:
1 Event.CLOSE 連接中斷事件。
2 Event.CONNECT 連接狀態(tài)事件,表示已經(jīng)成功連接了服務(wù)器。
3 IOErrorEvent.IO_ERROR 信息傳遞錯(cuò)誤事件,一般是由服務(wù)器地址錯(cuò)誤引起的。
4 ProgressEvent.SOCKET_DATA 服務(wù)器信息事件,當(dāng)收到服務(wù)器的新信息時(shí)被觸發(fā)。
==========================================
哈哈,經(jīng)過(guò)上面的代碼,我們的服務(wù)端MM和客戶端GG終于通過(guò)Socket這個(gè)緣分宿命的相遇了!接下來(lái)會(huì)發(fā)生什么?我們繼續(xù)往下看~~
三、第一封情書(shū)(客戶端發(fā)送消息,服務(wù)端接受消息)
客戶端GG在遇到服務(wù)端MM以后,終日變得茶飯不思,在折磨掉了無(wú)數(shù)根頭發(fā)以后,客戶端GG終于下定決心,要向服務(wù)端MM送出第一封情書(shū)啦!
既然是客戶端GG送出情書(shū),那我們先來(lái)看他到底是怎么做的:
==========================================
==客戶端代碼:Jclient2.mxml
==========================================
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12" creationComplete="initApp()"> <mx:Script> <![CDATA[ import flash.net.Socket; import flash.utils.ByteArray; private var socket:Socket=new Socket(); //定義Socket,準(zhǔn)備好情書(shū)的信封 //初始化程序 internal function initApp():void { socket.connect("localhost",719); //連接服務(wù)器 socket.addEventListener(Event.CONNECT,funConnect); //監(jiān)聽(tīng)是否連接 socket.addEventListener(Event.CLOSE,funClose); //監(jiān)聽(tīng)連接關(guān)閉 } internal function funConnect(event:Event):void { myText.text+="連接已建立 \n"; } internal function funClose(event:Event):void { myText.text+="連接已關(guān)閉 \n"; } internal function sendMessage(msg:String):void//發(fā)送數(shù)據(jù)對(duì)應(yīng)按鈕click事件 { var message:ByteArray=new ByteArray();//新建一個(gè)ByteArray存放數(shù)據(jù) message.writeUTFBytes(msg +"\r\n");//寫(xiě)入數(shù)據(jù),writeUTFBytes方法,以u(píng)tf-8格式傳數(shù)據(jù)避免中文亂碼 socket.writeBytes(message); //寫(xiě)入Socket的緩沖區(qū) socket.flush(); //調(diào)用flush方法發(fā)送信息 myText.text+=msg+"\r\n"; //在客戶端屏幕上輸出發(fā)送的內(nèi)容 myInput.text=""; //清空發(fā)言框 } ]]> </mx:Script> <mx:TextArea x="10" y="10" width="703" height="263" id="loveText"/> <mx:TextInput x="10" y="297" width="605" id="loveInput"/> <mx:Button x="648" y="297" label="發(fā)送情書(shū)" id="sendBtn" click="sendMessage(loveInput.text)"/> </mx:Application>
?嘎嘎,情書(shū)的做法就上面那面簡(jiǎn)單,注釋已經(jīng)寫(xiě)得很清楚了,就不多說(shuō)了。
OK,客戶端GG的情書(shū)倒是送出去了,我們就來(lái)看看服務(wù)端MM是怎么接受這封情書(shū)的呢?
==========================================
==服務(wù)端代碼:Jserver2.java
==========================================
import java.net.*; import java.io.*; public class Jserver2{ private BufferedReader reader; //負(fù)責(zé)輸入 private ServerSocket server; //服務(wù)器套接字 private Socket socket; //套接字 public Server2(){} //缺省構(gòu)造函數(shù) void startServer() //啟動(dòng)服務(wù)器 { try { server=new ServerSocket(719); //創(chuàng)建服務(wù)器套接字 System.out.println("服務(wù)器套接字建立完畢"); while(true) { System.out.println("等待客戶端GG"); socket=server.accept(); //若客戶端GG提出連接請(qǐng)求,與socket連接 System.out.println("完成與客戶端的連接"); reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8")); //獲取socket輸入流,“utf-8”這個(gè)編碼設(shè)置是為了更好顯示中文 getMessage();//讀取來(lái)自客戶端的數(shù)據(jù),并輸出至畫(huà)面上 } }catch(Exception e) { System.out.println(e); }finally{ try { if(server!=null) server.close();//關(guān)閉服務(wù)器套接字。 }catch(IOException ie){} } } void getMessage() //讀取來(lái)自套接字的信息 { try { while(true) //循環(huán) { System.out.println("客戶端GG說(shuō):"+reader.readLine()); } }catch(Exception e){} finally{ System.out.println("客戶端中斷連接"); try { if(reader!=null) reader.close(); //關(guān)閉套接字的輸入流 if(socket!=null) socket.close(); //關(guān)閉套接字 reader=null; socket=null; }catch(Exception e){} } } public static void main(String[] args) { Server2 server=new Server2(); server.startServer(); } }
?哈哈,我們運(yùn)行來(lái)看看,我們的客戶端GG的情書(shū)能否順利到達(dá)服務(wù)端MM的手中呢?
運(yùn)行結(jié)果如下:
HOHO 看樣子我們的客戶端GG的情書(shū),服務(wù)端MM是順利接受到啦。
四、服務(wù)端MM的心思(多客戶端通信)
在服務(wù)端MM收到客戶端GG的情書(shū)以后,突然發(fā)現(xiàn)自己原來(lái)還是蠻受歡迎的呢。但是有句俗話說(shuō)的好,那就是“不能為了一棵樹(shù)放棄一片森林”。所以服務(wù)端MM就想,能不能多接受幾個(gè)客戶端GG的情書(shū)呢?(真TMD賤。。。)
OK,既然服務(wù)端MM有了這個(gè)需求(雖然是很賤的需求),那我們就要來(lái)滿足她!
來(lái)看服務(wù)端的代碼:
=========================================
==Jserver3.java
=========================================
import java.net.*; import java.io.*; import java.util.*; public class Jserver3 { private ServerSocket server; List sManager = new ArrayList(); public Jserver3(){} void startServer() //運(yùn)行服務(wù)器 { try { server=new ServerSocket(719); System.out.println("服務(wù)器套接字已創(chuàng)建成功!"); while(true) { Socket socket=server.accept(); System.out.println("已經(jīng)與客戶端連接"); new J_Thread(socket).start(); sManager.add(socket); System.out.println("當(dāng)前客戶端連結(jié)數(shù):"+sManager.size()); } }catch(Exception e){}finally { try { server.close(); }catch(Exception e){} } } public static void main(String[] args) { Jserver3 server=new Jserver3(); server.startServer(); } class J_Thread extends Thread //與客戶端進(jìn)行通信的線程類(lèi) { Socket socket; //套接字引用變量 private DataInputStream reader; //套接字輸入流 private DataOutputStream writer; //套接字輸出流 J_Thread(Socket socket) //構(gòu)造函數(shù) { this.socket=socket; } public void run() { try { reader=new DataInputStream(socket.getInputStream());//獲取套接字的輸入流 writer=new DataOutputStream(socket.getOutputStream());//獲取套接字的輸出流 String msg; while((msg=reader.readUTF())!=null)//如果收到客戶端發(fā)來(lái)的數(shù)據(jù) { //向客戶端發(fā)送信息 writer.writeUTF("您的情書(shū)已經(jīng)收到"); writer.flush(); System.out.println("來(lái)自客戶端:"+msg); } }catch(Exception e){}finally { try { sManager.remove(socket); //刪除套接字 //關(guān)閉輸入輸出流及套接字 if(reader!=null)reader.close(); if(writer!=null)writer.close(); if(socket!=null)socket.close(); reader=null; writer=null; socket=null; System.out.println("客戶端離開(kāi)");//向屏幕輸出相關(guān)信息 System.out.println("當(dāng)前客戶端的連接數(shù):"+sManager.size()); }catch(Exception e){} } } } }
?嘎嘎 在這段代碼里,服務(wù)端MM為每一個(gè)連接的客戶端GG分配一個(gè)單獨(dú)的線程,而每一個(gè)線程里都持有對(duì)應(yīng)的客戶端GG的Socket對(duì)象。SO,通過(guò)這些多線程,服務(wù)端MM就練就了一心N用的功力,可以同時(shí)接受N個(gè)客戶端GG發(fā)來(lái)的情書(shū)了( ,真的太賤了。。。。)
客戶端的代碼和上面的客戶端代碼一模一樣的,這里就不多說(shuō)啦!
好了,在這里就簡(jiǎn)單的給大家介紹了如何實(shí)現(xiàn)java和flash(
flex
)實(shí)現(xiàn)socket通信的簡(jiǎn)單功能。有時(shí)間的話,再給大家來(lái)個(gè)簡(jiǎn)單的聊天室實(shí)現(xiàn)(那個(gè)時(shí)候的服務(wù)端MM就更賤了,不僅收著N多客戶端GG的情書(shū),竟然還把情書(shū)廣播給所有的客戶端GG,BS!)。嘎嘎 其實(shí)原理就是上面所說(shuō)的這些,大家自己都可以嘗試下。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
