1. 程式人生 > >java第22天----編碼問題,網路通訊,TCP,

java第22天----編碼問題,網路通訊,TCP,

文章目錄

昨天知識總結

  • 1.轉換流
  • 2.多個輸入源輸出源的組合
  • 3.更換輸入源輸出源
  • 4.列印流
    • 位元組列印流
    • 字元列印流
  • 5.序列流,資料流,記憶體流
  • 6.Properties
  • 7.序列化流

編碼問題

  • 轉換流的編碼:
  • 常用字符集:
    • 中國的:GBK/GB2312---------2個位元組
    • 歐洲的:ISO8859-1---------不支援中文,但是一個漢字對應1個位元組
    • 國標:UTF-8---------3個位元組
    • 內部編碼:unicode------2個位元組
    • 美國的:ASCII
  • 編碼:由字串轉成byte的過程
  • 解碼:由byte轉成字串的過程
  • 亂碼:編碼與解碼的過程中,使用了不同的字符集,造成編碼錯誤,出現了亂碼
  • 常見的出現亂碼的組合:
    • 使用GBK編碼,ISO8859-1解碼 或者UTF-8編碼,ISO8859-1解碼
    • 舉例:使用GBK編碼,UTF-8解碼 或者UTF-8編碼,GBK解碼
    public static void main(String[] args) throws IOException {
		//寫的時候採用UTF-8編碼
		writeData1();
		readData1();//使用utf-8字符集
		readData2();//使用GBK字符集
		
		//寫的時候採用GBK編碼
		writeData2
(); readData3();//使用utf-8字符集 readData4();//使用GBK字符集 } //寫出 //編碼格式是utf-8 public static void writeData1() throws IOException { OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("utf8.txt"),"utf-8"); outputStreamWriter.write("冰冰"); outputStreamWriter.close(); } //寫出
//編碼格式是GBK public static void writeData2() throws IOException { //建立輸出流並關聯檔案 第一個引數是位元組輸出流 第二個引數是:輸出時指定的編碼格式 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("GBK.txt"),"GBK");//預設GBK outputStreamWriter.write("冰冰"); outputStreamWriter.close(); } //讀入 //編碼格式是utf8 public static void readData1() throws IOException { InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("utf8.txt"),"utf-8"); char[] arr = new char[100]; int num = inputStreamReader.read(arr); System.out.println("readData1:"+new String(arr,0,num)); inputStreamReader.close(); } //讀入 //編碼格式是GBK public static void readData2() throws IOException { InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("utf8.txt"),"GBK");//預設utf8 char[] arr = new char[100]; int num = inputStreamReader.read(arr); System.out.println("readData2:"+new String(arr,0,num)); inputStreamReader.close(); } //讀入 //編碼格式是utf8 public static void readData3() throws IOException { InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("GBK.txt"),"utf-8"); char[] arr = new char[100]; int num = inputStreamReader.read(arr); System.out.println(new String(arr,0,num)); inputStreamReader.close(); } //讀入 //編碼格式是utf8 public static void readData4() throws IOException { InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("GBK.txt"),"GBK");//預設GBK char[] arr = new char[100]; int num = inputStreamReader.read(arr); System.out.println(new String(arr,0,num)); inputStreamReader.close(); }
  • 研發中的編碼:
  • 說明:GBK,UTF-8是支援中文的,ISO8859-1不支援中文
  • 編碼:
  • byte[] getBytes() //對於中文 預設的格式
  • 使用平臺的預設字符集將此 String 編碼為 byte 序列,
  • 並將結果儲存到一個新的 byte 陣列中。
  • byte[] getBytes(Charset charset)
  • 使用給定的 charset 將此 String 編碼到 byte 序列,並將結果儲存到新的 byte 陣列。
  • 解碼:
  • String(byte[] bytes) //對於中文 預設是格式
  • 通過使用平臺的預設字符集解碼指定的 byte 陣列,構造一個新的 String。
  • String(byte[] bytes, Charset charset)
  • 通過使用指定的 charset 解碼指定的 byte 陣列,構造一個新的 String。
public static void main(String[] args) throws UnsupportedEncodingException {
		//使用GBK編碼解碼
		String s1 = "你好";
		byte[] bs1 = s1.getBytes("GBK");//編碼
		System.out.println(new String(bs1,"GBK"));
		System.out.println(Arrays.toString(bs1));
		//使用UTF-8編碼解碼
		String s2 = "你好";
		byte[] bs2 = s1.getBytes("UTF-8");//編碼
		System.out.println(new String(bs2,"UTF-8"));
		System.out.println(Arrays.toString(bs2));
		//使用ISO8859-1編碼解碼
		String s3 = "你好";
		byte[] bs3 = s1.getBytes("ISO8859-8");//編碼
		System.out.println(new String(bs3,"ISO8859-8"));
		System.out.println(Arrays.toString(bs3));
	}

解決亂碼

  • 解決亂碼:
  • 出現的情況:編碼與解碼字符集不一樣
  • 解決方法:通過再編碼再解碼解決亂碼,但是實在保證第一次編碼沒有問題的前提下 在這裡插入圖片描述
  • 是否可以採用在編碼再解碼解決
編碼 解碼 可行性
GBK UTF-8 不可以
GBK ISO8859-8 可以
UTF GBK 不可以
UTF ISO8859-8 可以
ISO8859-1 GBK 不可以(編碼就出錯了)
ISO8859-1 UTF-8 不可以(編碼就出錯了)在這裡插入圖片描述

在這裡插入圖片描述

	public static void main(String[] args) throws UnsupportedEncodingException {
		//1.GBK編碼    UTF-8解碼
//		String s1 = "你好";
//		byte[] bs1 = s1.getBytes("GBK");
//		String strbs1 = new String(bs1, "utf-8");
//		System.out.println("utf8解碼:"+strbs1);//utf8解碼:���
//		
//		//再編碼
//		byte[] bs11 = strbs1.getBytes("utf-8");
//		//再解碼
//		System.out.println(new String(bs11,"GBK"));//錕斤拷錕�
		
		//2.GBK編碼         ISO8859-1解碼
//		String s1 = "你好";
//		byte[] s1b = s1.getBytes("GBK");
//		String sr1b = new String(s1b,"ISO8859-1");
//		System.out.println("ISO8859-1解碼:"+sr1b);//????
//		
//		//再編碼
//		byte[] s1bb = sr1b.getBytes("ISO8859-1");
//		//再解碼
//		System.out.println("GBK再編碼:"+new String(s1bb,"GBK"));//你好
		
		//3.utf8編碼         GBK解碼
		String s1 = "你好啊";
		byte[] s1b = s1.getBytes("utf-8");
		String sr1b = new String(s1b,"GBK");
		System.out.println("GBK解碼:"+sr1b);//浣犲ソ鍙?
		
		//再編碼
		byte[] s1bb = sr1b.getBytes("GBK");
		//再解碼
		System.out.println("utf8再編碼:"+new String(s1bb,"utf-8"));//你好??
		//4.utf8編碼         ISO8859-1解碼
//		String s1 = "你好號";
//		byte[] s1b = s1.getBytes("utf-8");
//		String sr1b = new String(s1b,"ISO8859-1");
//		System.out.println("ISO8859-1解碼:"+sr1b);//????????·
//		
//		//再編碼
//		byte[] s1bb = sr1b.getBytes("ISO8859-1");
//		//再解碼
//		System.out.println("utf8再編碼:"+new String(s1bb,"utf-8"));//你好號
	}

網路通訊

  • 網路程式設計的基礎
  • 網路的通訊:三要素:協議,IP,埠
  • 1.IP:在網路上惟一的標記一臺主機 127.0.0.1:保留地址,本地地址 javajiang IP面向物件了形成的類叫InetAddress
  • 2.埠:區分一臺主機上的多個服務區,取值範圍為(0,65535) 注意:在通訊時要保證客戶和伺服器端使用的埠號一致
  • 3.協議:制定的一個統一的標準 在這裡插入圖片描述

七層協議

  • 七層協議:

  • 應用層:與其他計算機進行通訊的一個應用,它是對應應用程式的通訊服務的。例如:一個沒有通訊功能的自處理程式就不能執行通訊程式碼,從事字處理工作的程式設計師也不關心OSI的第7層。但是,如果添加了一個傳輸檔案的選項,那麼字處理器的程式設計師就需要實現OSI的第七層。

  • 示例:TELNET HTTP FTP NFS SMTP等。

  • 表示層

  • 這一層的主要功能是定義資料格式及加密,例如,FTP允許比選擇以二進位制或ASCII格式傳輸,如果選擇二進位制,那麼傳送方和接收方不改變檔案的內容。如果選擇ASCII格式,傳送放將把文字從傳送方的字符集轉換成標準的ASCII後傳送資料。在接受方將標準的ASCII轉換成接收方計算機的字符集。

    • 例項:加密,ASCII等
  • 會話層:

  • 他定義瞭如何開始。控制和結束一個回話,包括對多個雙向訊息的控制和管理,一遍在只完成連續訊息的一部分是可以通知應用,從而使表示層看到的資料是連續的,在某些情況下,如果表示層收到了所有的資料,則用資料代表表示層。、

    • 例項RPC,SQL等
  • 傳輸層

  • 這層的功能包括是否選擇差錯恢復協議還是無差錯恢復協議,及在統一主機上對不同應用的資料流的輸入進行服用,還包括對收到的順序不對的資料包的重新排序功能,

    • 示例:TCP,UDP,SXP。
  • 網路層

  • 這層對端到端的包傳輸進行定義,它定義了能夠標識所有結點的邏輯地址,還定義了路由實現的方式和學習的方式。為了適應最大傳輸單元長度小於包長度的傳輸介質, 網路層還定義瞭如何將一個包分解成更小的包的分段方法。

  • 示例:IP,IPX等。

  • 資料鏈路層 它定義了在單個鏈路上如何傳輸資料。這些協議與被討論的各種介質有關。

    • 示例:ATM,FDDI等。
  • 物理層

  • OSI的物理層規範是有關傳輸介質的特性標準,這些規範通常也參考了其他組織制定的標準。連線頭、幀、幀的使用、電流、編碼及光調製等都屬於各種物理層規範中的內容。物理層常用多個規範完成對所有細節的定義。

  • 示例:Rj45,802.3等

獲取主機

    public static void main(String[] args) throws UnknownHostException {
		//IP地址:java面向物件後形成的類InetAddress
		//獲取自己的主機
		InetAddress address1 = InetAddress.getLocalHost();
		System.out.println(address1.getHostName());
		System.out.println(address1.getHostAddress());
		
		//獲取網路上任意一臺主機
		InetAddress address2 = InetAddress.getByName("www.baidu.com");//域名
		System.out.println(address2.getHostName());
		System.out.println(address2.getHostAddress());
	}

TCP/UDP

  • 網路通訊之Socket通訊:TCP/UDP
  • TCP與UDP通訊的區別:
  • TCP與UDP通訊的區別:
TCP UDP
是建立在連線的基礎上 建立在非連線的基礎上
安全性高 安全性低
傳輸速度低 速度高
4.適合傳輸資料量大的資料 資料量小的資料
  • 客戶端(app/瀏覽器)
  • 伺服器端:!=主機
  • 埠號:同一臺主機上的每一個伺服器的都擁有自己的埠號,取值範圍(0,65535),常用的埠:80,8080
  • 注意點:
    • 1.要保證客戶端和伺服器端的埠號一致
    • 2.要保證同一臺主機上的不同伺服器埠號不同

UDP

  • 客戶端
  • 實現過程:
    • 1.建立UDP通訊的物件----socket物件,對應的類是DatagramSocket(用於UDP通訊資料的傳送與接收)
    • 2.資料的封裝–裝包(打包),DatagramPacket(資料包,包括相關的屬性,資料等)
    • 3.傳送–呼叫send方法傳送
    • 4.關閉資源
    public static void main(String[] args) throws IOException {
//		 * 1.建立UDP通訊的物件----socket物件,對應的類是DatagramSocket(用於UDP通訊資料的傳送與接收)
		DatagramSocket datagramSocket = new DatagramSocket();
//		 * 2.資料的封裝--裝包(打包),DatagramPacket(資料包,包括相關的屬性,資料等)
		/*
		 * 第一個引數:包的內容
		 * 第二個引數:資料的長度
		 * 第三個引數:副武器的主機物件
		 * 第四個引數:伺服器的埠
		 */
		byte[] buf = "bingbing".getBytes();
		DatagramPacket datagramPacket = new DatagramPacket(buf,buf.length, InetAddress.getLocalHost(),20000);//埠與伺服器一致
//		 * 3.傳送--呼叫send方法
		datagramSocket.send(datagramPacket);
//		 * 4.關閉資源
		datagramSocket.close();
	}
  • 伺服器端----接受資料
  • 1.建立socket物件,繫結埠
  • 2.建立包物件,建立空陣列,準備接受傳過來的資料
  • 3.接收資料
  • 4.關閉資源
	public static void main(String[] args) throws IOException {
//		 * 1.建立socket物件
		DatagramSocket Socket = new DatagramSocket(20000);
//		 * 2.建立包物件,建立空陣列,準備接受傳過來的資料
		byte[] buf = new byte[1024];
		DatagramPacket Packet = new DatagramPacket(buf, buf.length);
//		 * 3.接收資料--當伺服器運轉起來,這個方法會一致處於堅挺狀態。
		Socket.receive(Packet);

		//將資料從包中取出
		byte[] arr = Packet.getData();
		System.out.println(new String(arr));
//		 * 4.關閉資源
		Socket.close();
	}

TCP

  • 客戶端
  • 在使用者端與伺服器端通訊的時候,對於客戶端既要進行輸入又要進行輸出,所以Socket物件的內部就內建了輸入流和輸出流
  • 當進行資料傳輸的時候,將資料放入socket物件的內部,將socket物件傳到伺服器端,相當於在客戶端與伺服器端建立了一個通道,
  • 兩者使用同一個socket物件。 在這裡插入圖片描述
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1.建立Socket物件,並繫結伺服器的埠和主機地址
		Socket socket = new Socket(InetAddress.getLocalHost(),30000);
		//2.準備資料
		String data = "BigData1715,你好";
		//3.獲取Socket物件內部的輸出流
		OutputStream outputStream = socket.getOutputStream();
		//4.將資料寫入網路
		outputStream.write(data.getBytes());
		
		//接收從伺服器回傳的資料
		InputStream inputStream = socket.getInputStream();
		byte[] bs = new byte[103];
		int num = 0;
		num = inputStream.read(bs);
		System.out.println(new String(bs,0,num));
		
		//資料的關閉
		outputStream.close();
		socket.close();
		
	}
  • 伺服器端
	public static void main(String[] args) throws IOException {
		//1.建立ServerSocket物件並繫結埠
		ServerSocket serverSocket = new ServerSocket(30000);
		//2.接收套接字---socket物件accept()方法會一直處於監聽狀態
		Socket socket = serverSocket.accept();
		//3.獲取輸入流
		InputStream inputStream = socket.getInputStream();
		//4.將內容寫到控制檯
		byte[] bs = new byte[3];
		int num = 0;
		num = inputStream.read(bs);
		System.out.println(new String(bs,0,num));
//		while((num = inputStream.read(bs))!= -1) {
//			System.out.print(new String(bs,0,num));
//		}
		System.out.println("qersadfseara");
		//完成資料的回傳
		OutputStream outputStream = socket.getOutputStream();
		outputStream.write("你好,BigData1715".getBytes());
		//5.關閉流
		outputStream.close();
		serverSocket.close();
		
	}