天天看點

java學習總結:網絡程式設計

Java 網絡程式設計

網絡程式設計是指編寫運作在多個裝置(計算機)的程式,這些裝置都通過網絡連接配接起來。

java.net 包中 J2SE 的 API 包含有類和接口,它們提供低層次的通信細節。你可以直接使用這些類和接口,來專注于解決問題,而不用關注通信細節。

java.net 包中提供了兩種常見的網絡協定的支援:

TCP:TCP 是傳輸控制協定的縮寫,它保障了兩個應用程式之間的可靠通信。通常用于網際網路協定,被稱 TCP / IP。

面向連接配接(三次握手),資料安全,速度略低,分為用戶端和服務端

三次握手:用戶端先向服務端發起請求,服務端響應請求,傳輸資料

UDP:UDP 是使用者資料報協定的縮寫,一個無連接配接的協定。提供了應用程式之間要發送的資料的資料包。

面向連接配接,資料不安全,速度快,不區分用戶端和服務端

java學習總結:網絡程式設計

Socket 程式設計

套接字使用TCP提供了兩台計算機之間的通信機制。 用戶端程式建立一個套接字,并嘗試連接配接伺服器的套接字。

當連接配接建立時,伺服器會建立一個 Socket 對象。用戶端和伺服器現在可以通過對 Socket 對象的寫入和讀取來進行通信。

java.net.Socket 類代表一個套接字,并且 java.net.ServerSocket 類為伺服器程式提供了一種來監聽用戶端,并與他們建立連接配接的機制。

以下步驟在兩台計算機之間使用套接字建立TCP連接配接時會出現:

  1. 伺服器執行個體化一個 ServerSocket 對象,表示通過伺服器上的端口通信。
  2. 伺服器調用 ServerSocket 類的 accept() 方法,該方法将一直等待,直到用戶端連接配接到伺服器上給定的端口。
  3. 伺服器正在等待時,一個用戶端執行個體化一個 Socket 對象,指定伺服器名稱和端口号來請求連接配接。
  4. Socket 類的構造函數試圖将用戶端連接配接到指定的伺服器和端口号。如果通信被建立,則在用戶端建立一個 Socket

    對象能夠與伺服器進行通信。

  5. 在伺服器端,accept() 方法傳回伺服器上一個新的 socket 引用,該 socket 連接配接到用戶端的 socket。

連接配接建立後,通過使用 I/O 流在進行通信,每一個socket都有一個輸出流和一個輸入流,用戶端的輸出流連接配接到伺服器端的輸入流,而用戶端的輸入流連接配接到伺服器端的輸出流。

TCP 是一個雙向的通信協定,是以資料可以通過兩個資料流在同一時間發送.以下是一些類提供的一套完整的有用的方法來實作 socket。

java學習總結:網絡程式設計

網絡程式設計(練習)

用戶端

package com.udp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Test1_Client {
	/*
	 * 用戶端向伺服器寫入字元串(鍵盤錄入),伺服器(多線程)将字元串反轉後寫回,用戶端讀取到的是反轉後的字元串
	 */

	public static void main(String[] args) throws UnknownHostException, IOException {
		Scanner sc = new Scanner(System.in);		// 建立鍵盤錄入對象
		Socket socket = new Socket("127.0.0.1",54321);//建立用戶端,指定ip位址和端口号
		
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //擷取輸入法
		PrintStream ps = new PrintStream(socket.getOutputStream());  //擷取輸出流
		
		ps.println(sc.nextLine());//将字元串寫到伺服器去
		System.out.println(br.readLine()); //将反轉後的結果讀出來
	}

}

           

服務端

package com.udp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.zip.InflaterInputStream;

public class Test1_Server {

	public static void main(String[] args) throws IOException {
		/*
		 * 用戶端向伺服器寫入字元串(鍵盤錄入),伺服器(多線程)将字元串反轉後寫回,用戶端讀取到的是反轉後的字元串
		 */
		ServerSocket server = new ServerSocket(54321);
		System.out.println("伺服器啟動,綁定54321端口");
		
		while(true) {
			final Socket socket = server.accept();     //接受用戶端的請求
			new Thread() {
				public void run() {
					try {
						BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
						PrintStream ps = new PrintStream(socket.getOutputStream());  //擷取輸出流
						String line = br.readLine();			//将用戶端寫過來的資料讀取出來
						line = new StringBuilder(line).reverse().toString();  //鍊式程式設計
						ps.println(line);
						
						socket.close();
					}catch (IOException e ) {
						e.printStackTrace();
					}
				}
			}.start();
		}
	}

}

           

練習(用戶端向伺服器上傳檔案)

用戶端

package com.udp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Test2_UpdataClient {

	public static void main(String[] args) throws UnknownHostException, IOException {
		//1.提示輸入要上傳的檔案路徑,驗證路徑是否存在以及是否是檔案夾
		File file  = getFile();
		//2.發送檔案名到服務端
		Socket socket = new Socket("127.0.0.1",12345);
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		PrintStream ps = new PrintStream(socket.getOutputStream());
		ps.println(file.getName());
		//6.接收結果,如果存在給與提示,程式直接退出
		String result = br.readLine();
		if("存在".equals(result)) {
			System.out.println("您上傳的檔案已經存在請不要重複上傳");
			socket.close();
			return;
		}
		//7.如果不存在,定義FileInputStrean讀取檔案,寫到網絡
		FileInputStream fis = new FileInputStream(file);
		byte[] arr = new byte[8192];
		int len;
		while((len = fis.read(arr)) != -1) {
			ps.write(arr,0,len);
		}
		fis.close();
		socket.close();
	}
	private static File getFile() {
				Scanner sc = new Scanner(System.in);
				System.out.println("請輸入一個檔案路徑:");
				while(true ) {
					String line = sc.nextLine();
					File file = new File(line);
					if(!file.exists()) {
						System.out.println("您錄入的檔案路徑不存在,請輸入");
					}
				}
				return null;
			}
	}

           

伺服器

package com.udp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Test2_UpdataServer {

	private static ServerSocket server;

	public static void main(String[] args) throws IOException {
		//3.建立多線程
		ServerSocket sercer = new ServerSocket(12345);
		System.out.println("伺服器啟動,綁定12345端口号");
		
		//4.讀取檔案名
		while(true)  {
			final Socket socket = server.accept();
			new Thread() {
				public void run() {
					try {
						InputStream is = socket.getInputStream();
						BufferedReader br = new BufferedReader(new InputStreamReader(is));
						PrintStream ps = new PrintStream(socket.getOutputStream());
						String fileName = br.readLine();
						//5.判斷檔案是否存在,将結果發回用戶端
						File dir = new File("updata");
						dir.mkdir();			//建立檔案夾
						File file = new File(dir,fileName);   //封裝成file對象
						
						if(file.exists()) {		//如果伺服器已經勳在這個檔案
							ps.println("存在");    //将存在寫給用戶端
							socket.close();
							return;
						}else {
							ps.println("不存在");
						}
						//8.定義fileoutputstream,從網絡讀取資料,存儲到本地
						FileOutputStream fos = new FileOutputStream(file);
						byte[] arr = new byte[8192];
						int len;
						
						while((len = is.read(arr)) != -1) {
							fos.write(arr,0 ,len);
						}
						fos.close();
						socket.close();
					}catch(IOException e) {
						e.printStackTrace();
					}
				}
			}.start();
		}
	}

}