1. 程式人生 > >Socket通訊實現伺服器和客戶端對話

Socket通訊實現伺服器和客戶端對話

廣域網和區域網

介紹socket通訊前我們先介紹一下廣域網與區域網的概念。區域網簡稱LAN,是指在某一區域幾臺計算機組成的計算機組,區域網是封閉的,區域網經常採用共享通道,即共用同一條電纜。廣域網簡稱WAN,是一種跨越大的,地域性的地區性網路集合廣域網包含大大小小不同的子網,可以是區域網,也可以是小型的廣域網。廣域網為每個單元分配IP地址,區域網也會其單元分配IP地址,這兩個IP地址互不干擾,一個對內,一個對外,區域網的IP只對其內部的計算機有效,它們可以通過IP相互訪問。如果你把一臺計算機連線到網際網路,網路提供商則會為你分配一個外網的IP。由此可見,IP地址將是我們接下來介紹的socket通訊需要用到的引數,這也是一個地址,來找到你要連線的計算機。在socket中我們除了用到IP還需要找到埠號,一個IP地址的埠通過16bit進行編號,最多可以有65536個埠。埠是通過埠號來標記的,埠號只有整數,範圍是從0 到65535,一臺主機可以有不同服務,即通過埠號進行區分。總之,我們通過IP地址+埠號來找到特定計算機的特定服務。

什麼是socket通訊

socket通訊及網路上的兩個程式通過一個雙向的通訊連線實現資料交換,這個連線的一段稱為一個socket,java中通過TCP握手協議(三次握手)為使用者提供程式設計介面。所謂“三次握手”即對每次傳送的資料量進行跟蹤進行協商使資料段的傳送和接收同步,根據所接收到的資料量而確定的資料確認數及資料傳送、接收完畢後撤消聯絡,並建立虛連線。java內部有相應的包,我們要學會如何去呼叫,接下來我們介紹一下怎麼寫一個簡易的可以實現兩個程式通過socket通訊實現對話的程式。

socket通訊程式實現

程式分為伺服器和客戶端兩個部分 1、伺服器:

public class Server {
	// IP
	// 埠號
	public static void main(String[] args) {
		try {
			ServerSocket serverSocket = new ServerSocket(9999); // 建立伺服器
			System.out.println("伺服器。。。。。。。。。。");
			Socket socket = serverSocket.accept(); // 處於阻塞,等待監聽。每接受一個執行緒,生成一個新使用者。
			InputStream in = socket.getInputStream(); // 得到輸入流,位元組流
			BufferedReader br = new BufferedReader(new InputStreamReader(in));// 把位元組轉為字元,然後可以read
			OutputStream out = socket.getOutputStream();// 得到輸出流
			PrintWriter pw = new PrintWriter(out); // 將輸出流包裝成列印流
			while (true) {
				String info = "";
				String temp = null;
				temp = br.readLine();
				info = temp;
				System.out.println("客戶端:" + info);
				Scanner scan = new Scanner(System.in);
				String str = scan.nextLine();
				pw.write(str+"\r\n"); //此處若不加\r\n會報錯
				pw.flush(); //清空
			}
			// 關閉資源
			// in.close();
			// br.close();
			// out.close();
			// socket.close();
			// serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

建立伺服器的基本思路是,先建立伺服器物件,並給其一個埠號。然後伺服器會處於阻塞狀態,如果接收到執行緒,則建立一個socket物件,就像是為資料搭建一個通道,然後讓socket得到位元組流,並把位元組轉字元。因為它是伺服器自然也要發資料,於是我們還要配置輸出,得到輸出流幷包裝為列印流。接下來就是一個while迴圈了,它將不斷執行收發資料的過程。這裡值得一提的是其中涉及到阻塞的程式碼,temp = br.readLine();這個語句如果沒有讀到資料則會一直等待,故此處沒有while也能有同樣的效果,在write後如果沒有加上等待資料傳送完畢的語句也不會影響到資料傳輸的完整性。另外千萬別忘記加上丟擲異常。 2、客戶端:

public class Client {
	public static void main(String[] args) {
		try {
			Socket socket = new Socket("localhost", 9999); // 本地主機
			System.out.println("客戶端。。。。。。。");
			OutputStream out = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(out);
			// pw.write(System.in.read());
			InputStream in = socket.getInputStream();
			InputStreamReader re = new InputStreamReader(in);// 改為字元流
			BufferedReader br = new BufferedReader(re);// 緩衝區
			while (true) {
				Scanner scan = new Scanner(System.in);
				String str = scan.nextLine();
				pw.write(str+"\r\n");
				pw.flush();
			    //socket.shutdownOutput(); //等待資料全部傳過來
				String info = "";
				String temp = null;
				temp = br.readLine(); // 行讀取
				info = temp;
				System.out.println("伺服器:" + info);
			}
			// 關閉
			// pw.close();
			// out.close();
			// in.close();
			// br.close();
			// socket.close();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

客戶端的程式碼和伺服器如出一轍,只是少了伺服器的建立以及收發資料的先後順序。客戶端需要通過相應的IP地址和埠號來找到伺服器,這裡因為我們使用的是本地電腦,那麼通過“localhost”就可以了,伺服器和客戶端我們都沒有加上socket以及相關資源的關閉,這是因為我們一直處在迴圈中,程式無法執行到這些程式碼,如果加上會報錯,大家可以注意一下這點。 以上程式碼便可以實現伺服器和客戶端不斷地聊天啦!