Java網路程式設計之Socket通訊(一)
最近在學習Java網路程式設計,之前聽說過,但是一直都沒有認真瞭解過。這幾天突然來了興致,覺得很神奇,忽然就想要了解下具體是什麼個情況。
Socket通常也稱作"套接字",用於描述IP地址和埠,是一個通訊鏈的控制代碼。在Internet上的主機一般運行了多個服務軟體,同時提供幾種服務。每種服務都開啟一個Socket,並繫結到一個埠上,不同的埠對應於不同的服務。
Socket非常類似於電話插座。以一個國家級電話網為例,電話的通話雙方相當於相互通訊的2個程序,區號是它的網路地址;區內一個單位的交換機相當於一臺主機,主機分配給每個使用者的局內號碼相當於Socket號。任何使用者在通話之前,首先要佔有一部電話機,相當於申請一個Socket;同時要知道對方的號碼,相當於對方有一個固定的Socket。然後向對方撥號呼叫,相當於發出連線請求(假如對方不在同一區內,還要撥對方區號,相當於給出網路地址)。假如對方在場並空閒(相當於通訊的另一主機開機且可以接受連線請求),拿起電話話筒,雙方就可以正式通話,相當於連線成功。雙方通話的過程,是一方向電話機發出訊號和對方從電話機接收訊號的過程,相當於向Socket傳送資料和從socket接收資料。通話結束後,一方掛起電話機相當於關閉Socket,撤消連線。
在電話系統中,一般使用者只能感受到本地電話機和對方電話號碼的存在,建立通話的過程,話音傳輸的過程以及整個電話系統的技術細節對他都是透明的,這也與Socket機制非常相似。Socket利用網間網通訊設施實現程序通訊,但它對通訊設施的細節毫不關心,只要通訊設施能提供足夠的通訊能力,它就滿足了。
以上這些都是百度百科裡面的定義與解釋,不過看著也還是蠻容易理解的,不像之前有的解釋很不容易理解,專業術語太多,理解起來特別費勁。
Socket通訊實現步驟:
1、建立ServerSocket和Socket
2、開啟連線Socket的輸入/輸出流
3、按照協議(通常是TCP/UDP)對Socket進行讀寫操作
4、關閉輸入/輸出流,關閉Socket
Socket通訊模型如下圖所示:
1、Server伺服器端:
a、建立ServerSocket物件,同時繫結監聽埠
b、通過accept()方法監聽客戶端的請求
c、建立連線後,通過輸入流讀取客戶端傳送的請求資訊
d、通過輸出流向客戶端傳送響應資訊
e、關閉相應資源
package com.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; /** * 基於TCP協議的服務端Socket通訊 * 伺服器端必須早於客戶端啟動 * @author feizi * */ public class ServerSocketDemo { public static void main(String[] args) { try { //1、建立一個服務端Socket,即ServerSocket物件,指定繫結的埠,並偵聽該埠 ServerSocket serverSocket = new ServerSocket(5555); //2、呼叫accept()方法開始偵聽客戶端請求,建立Socket,等待客戶端的連線 System.out.println("===================伺服器即將啟動,等待客戶端的連線==============="); Socket socket = serverSocket.accept(); //3、獲取輸入位元組流,讀取客戶端請求資訊 InputStream is = socket.getInputStream(); //將位元組流包裝成字元流 InputStreamReader isr = new InputStreamReader(is); //為字元輸入流新增緩衝 BufferedReader br = new BufferedReader(isr); //讀取字元輸入流中的資料資訊 String data = null; while(null != (data = br.readLine())){ System.out.println(new Date()); System.out.println("我是伺服器端,客戶端說:"+data); } //呼叫shutdown方法關閉輸入流 socket.shutdownInput(); //4、獲取輸出位元組流,響應客戶端的資訊 OutputStream os = socket.getOutputStream(); //將位元組流包裝成為字元列印流 PrintWriter pw = new PrintWriter(os); //向客戶端回覆響應訊息 pw.write("使用者名稱和密碼輸入正確"); //重新整理快取 pw.flush(); //關閉socket輸出流 socket.shutdownOutput(); //5、關閉資源 pw.close(); os.close(); br.close(); isr.close(); is.close(); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }
2、Client客戶端:
a、建立Socket物件,指明需要連線的伺服器的地址和埠號
b、建立連線後,通過輸出流向伺服器端傳送請求資訊
c、通過輸入流獲取伺服器的響應資訊
d、關閉相應資源
package com.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;
/**
* 基於TCP協議的客戶端Socket通訊
* @author feizi
*
*/
public class ClientSocketDemo {
public static void main(String[] args) {
try {
//1、建立客戶端Socket,指定伺服器地址和埠號,向服務端傳送請求資訊
Socket socket = new Socket("localhost", 5555);
//2、獲取輸出位元組流,向伺服器端傳送訊息
OutputStream os = socket.getOutputStream();
//3、將位元組輸出流包裝為字元列印流
PrintWriter pw = new PrintWriter(os);
//向伺服器端傳送請求資訊
StringBuffer bf = new StringBuffer();
bf.append("使用者名稱:").append("admin");
bf.append("密碼:").append("123");
pw.write(bf.toString());
//重新整理快取
pw.flush();
//關閉Socket的輸出流
socket.shutdownOutput();
//3、獲取輸入位元組流,讀取伺服器端的響應資訊
InputStream is = socket.getInputStream();
//將輸入位元組流包裝成字元字元流
InputStreamReader isr = new InputStreamReader(is);
//為字元流新增緩衝區
BufferedReader br = new BufferedReader(isr);
//通過伺服器端的響應資訊
String data = null;
while(null != (data=br.readLine())){
System.out.println(new Date());
System.out.println("我是客戶端,伺服器端說:"+data);
}
//關閉Socket輸入流
socket.shutdownInput();
//4、關閉資源
br.close();
isr.close();
is.close();
pw.close();
os.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
這篇只介紹到了單個客戶端與伺服器端之間的通訊,下一篇會介紹到利用執行緒實現多個客戶端與伺服器進行通訊。
好了,今天就到這兒了,每天學習一點點,不斷成長,不斷進步,不久你就會改變!