1. 程式人生 > >Java網路程式設計之Socket通訊(一)

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();
		}
	}

}

這篇只介紹到了單個客戶端與伺服器端之間的通訊,下一篇會介紹到利用執行緒實現多個客戶端與伺服器進行通訊。

好了,今天就到這兒了,每天學習一點點,不斷成長,不斷進步,不久你就會改變!