第一次接觸Socket是大二時的課程設計,當時做的是圖書管理系統,源碼都是網上下載,考試周拿著代碼天天磨,隱約中記得有Socket這麼一個單詞。
第二次是去年代表學校參加“河北省電子信息職業技能大賽”,接受曹建新師哥的培訓。建新師哥當時用手機Android軟件做客戶端,通過局域網向電腦端服務器傳輸手機錄入的信息。當時我很詫異,客戶端是Android平台,服務器是.Net平台,這兩種平台是如何在局域網內進行通信的呢?建新師哥的回答是:“通過Socket,把數據打包成JSON格式進行傳輸。”從此對Socket的認識便有了一種高大上的感覺。
第三次接觸是通過馬士兵老師的視頻,這次瞬間感覺Socket--So Easy。這也驗證了米老師的那句話:不怕不知道,就怕不知道。
Socket通信分為服務器Socket即ServerSocket和客戶端Socket。
在服務器端,通信前需要建立和客戶端的通信通道,建立對客戶端通信端口號的監聽;在客戶端,通信前需要定義進行通信的主機IP和端口號,創建通信通道。兩者都准備完畢,下面就可以進行通信了。
服務器端代碼:
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class TCPServer { public static void main(String[] args) { //創建向客戶端傳輸數據的通道 InputStream in = null; //創建從客戶端接收數據的通道 OutputStream out = null; try { //建立和客戶端的通信,並定義通信端口 ServerSocket ss = new ServerSocket(5888); //監聽客戶端提交的請求 Socket socket = ss.accept(); in = socket.getInputStream(); out = socket.getOutputStream(); //在字節流的基礎上進行包裝數據流 DataInputStream dis = new DataInputStream(in); DataOutputStream dos = new DataOutputStream(out); //接收客戶端提交的請求 String s = null; if ((s = dis.readUTF()) != null) { System.out.println(s); System.out.println("from:" + socket.getInetAddress()); System.out.println("port:" + socket.getPort()); } //向客戶端傳輸數據 dos.writeUTF("hi,hello"); dos.close(); dis.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }由於數據流的readUTF()方法和writeUTF()方法都是阻塞式,所以當A向B發送數據後,如果B沒有響應,A是無法繼續發送數據的,只能傻傻的等待。這個過程好比TCP/IP協議的三次握手,1:A呼叫B,“我是A,收到請回答?”;2:B回應A,“我是B,收到”;3:A繼續說,“我想請你吃飯,你有時間嗎?”。下面A和B就可以進行通信了。
服務器端代碼有了,下面分享客戶端代碼:
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class TCPClient { public static void main(String[] args) { //創建向服務器傳輸數據的通道 InputStream in = null; //創建從服務器接收數據的通道 OutputStream out = null; try { //定義進行通信的主機IP和端口號 Socket socket = new Socket("localhost", 5888); in = socket.getInputStream(); out = socket.getOutputStream(); //在字節流的基礎上進行包裝數據流 DataInputStream dis = new DataInputStream(in); DataOutputStream dos = new DataOutputStream(out); //向服務器提交數據 dos.writeUTF("hey"); //接收從服務器返回的數據 String s = null; if ((s = dis.readUTF()) != null) { System.out.println(s); } dos.close(); dis.close(); socket.close(); } catch (UnknownHostException e) { e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } } }通過這個簡單的小Demo,我們就可以清晰的觀察到Socket是如何在服務器端和客戶端進行通信的。
J2SE是JavaWeb和J2EE的基礎,異常處理、IO通道、線程、網絡編程、GUI編程又是J2SE的基礎,所以學好Socket很有必要。
席慕蓉說過一句名言:前世的五百次回眸才能換得今生的一次擦肩而過。所以對於以後的每次擦肩而過都應該認真對待,不要像我,和Socket都擦肩而過好多次了,今天才終於認識它。