對Socket的一點我的理解:Socket原意是指插座。家家戶戶都有五花八門的家用電器,但它們共用統一制式的插座。這樣作的好處就是將全部家用電器的通電方式統一化,不須要大費周章地在牆壁上鑿洞並專門接電線把家用電器和牆壁中的入戶線接在一塊兒。java
將其對應於計算機中的網絡通訊:在TCP/IP網絡的分層模型中,Socket是一組用於應用程序間進行網絡通訊的庫函數,並位於應用層和傳輸層之間。有了Socket,一方面能夠屏蔽底層通訊軟件和具體操做系統之間的差別,使任意兩臺安裝了TCP/IP協議組件和套接字規範的計算機進行通訊成爲可能;另外一方面,多種多樣的應用程序就有了統一的網絡編程的接口,而不須要和底層的傳輸層直接打交道,這就大大簡化了網絡編程的過程。編程
簡單來講,Socket的通訊機制就是,通訊雙方的應用程序都有Socket,將網絡通訊統一爲Socket之間的通訊,數據則在Socket之間經過IO流進行傳輸。網絡
這裏咱們要模擬一個聊天室程序,衆所周知,聊天室應用因其系統自身比較簡單,不強調可靠性,所以適宜用UDP協議解決。多線程
UDPSocket應用分爲發送端和接收端兩部分。對於發送端,該應用的執行流程爲:ide
1.建立發送端Socket對象;函數
2.建立數據並打包;this
3.發送數據;spa
4.釋放傳輸資源。操作系統
對於接收端,該應用的執行流程爲:.net
1.建立接收端Socket對象;
2.建立接收的數據包,換句話說將接收到的數據存放在何處;
3.接收數據;
4.解包,解析接收的數據,並打印在屏幕上;
5.釋放傳輸資源。
此外,一個聊天室應用不只要進行發送,也要進行接收,兩者同時集成在同一應用上,所以必須經過多線程技術讓發送和接收兩個功能同時進行。
所以,對該程序的Java實現分爲三部分:發送端線程,接收端線程,主函數。
發送端線程的Java代碼實現爲:
1 package chatroom; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.DatagramPacket; 7 import java.net.DatagramSocket; 8 import java.net.InetAddress; 9 10 public class SendThread implements Runnable { 11 12 private DatagramSocket ds; 13 14 public SendThread(DatagramSocket ds) {//發送端類的構造函數 15 this.ds = ds; 16 } 17 18 @Override 19 public void run() { 20 try { 21 22 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//將用戶從鍵盤輸入的數據裝入字符緩衝輸入流 23 24 String line = null; 25 System.out.println("發送端:歡迎來到聊天室.你想在這裏說些什麼?"); 26 while ((line = br.readLine()) != null) { 27 byte[] bys = line.getBytes(); 28 DatagramPacket dp = new DatagramPacket(bys, bys.length,InetAddress.getByName("192.168.1.102"), 12306);//生成要發送的報文,在本例中發送端的目的地址就是本機 29 ds.send(dp);//發送數據報 30 if ("886".equals(line)) {//若是發送的數據是「886」,則說明聊天結束 31 break; 32 } 33 } 34 35 ds.close(); 36 } catch (IOException e) { 37 e.printStackTrace(); 38 } 39 } 40 41 }
接收端線程的Java代碼實現爲:
1 package chatroom; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 7 public class ReceiveThread implements Runnable { 8 private DatagramSocket ds; 9 10 public ReceiveThread(DatagramSocket ds) {//接收端類的構造函數 11 this.ds = ds; 12 } 13 14 @Override 15 public void run() { 16 try { 17 while (true) {//死循環,一直到收到886後跳出 18 byte[] bys = new byte[1024];//將接收的數據存於此處 19 DatagramPacket dp = new DatagramPacket(bys, bys.length);//建立要接收的數據包 20 ds.receive(dp);//接收數據 21 String ip = dp.getAddress().getHostAddress(); 22 String s = new String(dp.getData(), 0, dp.getLength()); 23 System.out.println("接收端:from " + ip + " data is : " + s);//打印接收到的數據 24 if ("886".equals(s)) { 25 break; 26 } 27 } 28 } catch (IOException e) { 29 e.printStackTrace(); 30 } 31 } 32 33 }
主函數的Java實現代碼爲:
1 package chatroom; 2 3 import java.io.IOException; 4 import java.net.DatagramSocket; 5 6 public class ChatRoom { 7 public static void main(String[] args) throws IOException { 8 DatagramSocket dsSend = new DatagramSocket();//發送端Socket 9 DatagramSocket dsReceive = new DatagramSocket(12306);//接收端Socket,接收端端口號設置爲12306 10 11 SendThread st = new SendThread(dsSend);//建立發送端 12 ReceiveThread rt = new ReceiveThread(dsReceive);//建立接收端 13 14 Thread t1 = new Thread(st);//建立發送端線程 15 Thread t2 = new Thread(rt);//建立接收端線程 16 17 t1.start(); 18 t2.start(); 19 } 20 }
實現效果以下圖所示:
關於Java自帶的Socket庫函數與Linux自帶的Socket系統調用之間的區別:
首先,兩者提供的接口不一樣;
第二,Java的Socket庫函數底層執行原理是JVM將Java程序解析出來的XML參數傳遞給C++程序,並將響應由C++程序回傳給Java程序;
第三,Java程序經過JVM機制保證了優良的跨平臺特性,一樣的程序能夠在任何操做系統下執行,而Linux下自帶的Socket編程,寫出的程序只能在Linux下運行。