1. 程式人生 > >java網路通訊之Socket通訊:TCP/UDP

java網路通訊之Socket通訊:TCP/UDP

網路通訊三要素:協議,IP,埠。七層協議。

package com.qianfeng.test;
/*
 * 網路程式設計基礎:
 * 網路的通訊:三要素:協議,IP,埠
 * 1.IP:在網路上唯一的標記一臺主機     127.0.0.1 :保留地址/本地地址        java將IP面向物件了形成的類叫InetAddress
 * 2.埠:一臺主機上的多個伺服器  取值範圍(0,65535)    注意:在通訊時要保證客戶端和伺服器端使用的埠號一致
 * 3.協議:制定的一個統一的標準
 * 
 * 
 * 七層協議:  瞭解
* 應用層
 
與其它計算機進行通訊的一個應用,它是對應應用程式的通訊服務的。
例如,一個沒有通訊功能的字處理程式就不能執行通訊的程式碼,
從事字處理工作的程式設計師也不關心OSI的第7層。但是,如果添加了一個
傳輸檔案的選項,那麼字處理器的程式設計師就需要實現OSI的第7層。
示例:TELNET,HTTP,FTP,NFS,SMTP等。

表示層

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

會話層

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

傳輸層

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

網路層

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

資料鏈路層

它定義了在單個鏈路上如何傳輸資料。這些協議與被討論的各種介質有關。示例:ATM,FDDI等。

物理層

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

public class Demo5 {
	
}

InetAddress類

package com.qianfeng.test;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class Demo6 {

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

網路通訊之Socket通訊:UDP客戶端

package com.qianfeng.test;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
 * 網路通訊之Socket通訊:TCP/UDP
 * 
 * TCP與UDP通訊的區別:
* 		TCP                             UDP
 * 1.是建立在連線的基礎上                                 建立在非連線的基礎上
 * 2.安全性更高							安全性低
 * 3.傳輸速度低							速度高
 * 4.適合傳輸資料量大的資料    				資料量小的資料
 * 
 * 客戶端:(app/瀏覽器)
 * 伺服器端:!=主機
 * 
 * 埠號:同一臺主機上的每一個伺服器都擁有自己的埠號,取值範圍(0,65535),常用的埠:80,8080
 * 注意點:1.要保證客戶端和伺服器端的埠號一致    2.要保證同一臺主機上的不同伺服器埠號不同
 * 
 *先講解UDP	注意:要先開啟伺服器端,再開啟客戶端。
 *客戶端
 *實現過程:
 * 1.建立UDP通訊的物件--socket物件,對應的類是DatagramSocket(用於UDP通訊資料的傳送和接收)
 * 2.資料的封裝--裝包(打包),DatagramPacket(資料包,包括相關的屬性,資料等)
 * 3.傳送--呼叫send方法
 * 4.關閉相關資源
 * 
 */
public class Demo7 {

	public static void main(String[] args) throws IOException {
		
//		* 1.建立UDP通訊的物件--socket物件,對應的類是DatagramSocket(用於UDP通訊資料的傳送和接收)
		DatagramSocket socket = new DatagramSocket();
		
//		* 2.資料的封裝--裝包(打包),DatagramPacket(資料包,包括相關的屬性,資料等)
		/*
		 * 第一個引數:包的內容
		 * 第二個:資料的長度
		 * 第三個:伺服器的主機物件
		 * 第四個:伺服器的埠
		 */
		byte[] buf = "bingbing".getBytes();
		DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 20000);//埠與伺服器端一致
//		* 3.傳送--呼叫send方法
		socket.send(packet);
//		* 4.關閉相關資源
		socket.close();
		
	}
}

網路通訊之Socket通訊:UDP伺服器端

package com.qianfeng.test;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/*
 * 伺服器端--接收資料
 * 1.建立socket物件,繫結埠
 * 2.建立包物件,建立空陣列,準備接收傳過來的資料
 * 3.接收資料
 * 4.關閉資源
 */
public class Demo8 {

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

實現隨時發隨時收—使用UDP(客戶端)

package com.qianfeng.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
 * 例項:實現隨時發隨時收---使用UDP
 * 
 * 客戶端
 */
public class Demo9 {
	public static void main(String[] args) throws IOException {
		DatagramSocket socket = new DatagramSocket();
		
		//獲取字元緩衝流實現從控制檯接收資料
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
		String data = null;
		while ((data = bufferedReader.readLine()) != null) {
			DatagramPacket packet = new DatagramPacket(data.getBytes(), data.getBytes().length, InetAddress.getLocalHost(), 20000);//埠與伺服器端一致
		
			//傳送
			socket.send(packet);
			
			//當用戶輸入over的時候代表結束
			if (data.equals("over")) {
				break;
			}
		}
		
		socket.close();
	}
}

實現隨時發隨時收—使用UDP(伺服器端)

package com.qianfeng.test;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/*
 * 伺服器端
 */
public class Demo10 {
    public static void main(String[] args) throws IOException {
    	DatagramSocket socket = new DatagramSocket(20000);
    	
    	//實現不斷的接收資料
    	while (true) {
    		byte[] buf = new byte[1024];
    		DatagramPacket packet = new DatagramPacket(buf, buf.length);
//    		 * 3.接收資料--當伺服器運轉起來,這個方法會一直處於監聽狀態.
    		socket.receive(packet);
    		//將資料從包中取出
    		byte[] arr = packet.getData();
    		String data = new String(arr);
    		System.out.println(data);
    		
			//當用戶輸入over的時候代表結束
			if (data.trim().equals("over")) {
				break;
			}
		}
    	
    	socket.close();
	}
}

TCP客戶端

package com.qianfeng.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 * TCP:
 * 客戶端
 * 在客戶端與伺服器端通訊的時候,對於客戶端既要進行輸入又要進行輸出,所以在Socket物件的內部就內建了輸入流和輸出流,
 * 當進行資料傳輸的時候,將資料放入socket物件的內部,將socket物件傳到伺服器端,相當於在客戶端與伺服器端建立了一個通道,
 * 兩端使用同一個socket物件.
 */
public class Demo11 {
	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[] arr = new byte[103];
//		int num = inputStream.read(arr);
//		System.out.println(new String(arr,0,num));
		
		int num = 0;
		while ((num = inputStream.read(arr)) != -1) {
			System.out.println(new String(arr,0,num));
		}
		//5.關閉資源
		//outputStream.close();
		socket.close();
	}
}

TCP伺服器端

package com.qianfeng.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * 伺服器端:
 */
public class Demo12 {
	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[] arr = new byte[103];
		int num = inputStream.read(arr);
		System.out.println(new String(arr,0,num));
		
//		int num = 0;
//		while ((num = inputStream.read(arr)) != -1) {
//			System.out.print(new String(arr,0,num));
//		}
		
		//完成資料的回傳
		OutputStream outputStream = socket.getOutputStream();
		outputStream.write("你好,BigData1715".getBytes());
		
		//5.關閉資源
		serverSocket.close();
	}
}

TCP例項:實現大小寫轉換(客戶端)

package com.qianfeng.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.DatagramPacket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 * TCP例項:實現大小寫轉換
 *客戶端
 *
 */
public class Demo13 {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1.建立Socket物件並繫結伺服器的埠和主機地址
		Socket socket = new Socket(InetAddress.getLocalHost(), 30001);
		
		//2.準備資料
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
		
		//注意:這裡最好使用原始的流
		//3.獲取socket內部的輸入流與輸出流
		InputStream inputStream = socket.getInputStream();
		OutputStream outputStream = socket.getOutputStream();
		PrintWriter printWriter = new PrintWriter(outputStream,true);//當第二個引數為true的時候會自動重新整理,
		//當執行println、printf 或 format 方法的時候
		
		String data = null;
		while ((data = bufferedReader.readLine()) != null) {
			//傳送
//			outputStream.write(data.getBytes());
//		    outputStream.flush();
			printWriter.println(data);
		    
		    //接收伺服器端的資料
		    byte[] arr = new byte[100];
		    int num = inputStream.read(arr);
		    System.out.println(new String(arr,0,num));
			
			//當用戶輸入over的時候代表結束
			if (data.equals("over")) {
				break;
			}
		}
		
		socket.close();
	}
}

TCP例項:實現大小寫轉換(伺服器端)

package com.qianfeng.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * 伺服器端
 */
public class Demo14 {
	public static void main(String[] args) throws IOException {
		//1.建立ServerSocket物件並繫結埠
		ServerSocket serverSocket = new ServerSocket(30001);
		//2.接收套接字---socket物件,accept方法會一直處於監聽狀態
		Socket socket  = serverSocket.accept();
		//3.獲取輸入流
		InputStream inputStream = socket.getInputStream();
		OutputStream outputStream = socket.getOutputStream();
		PrintWriter printWriter = new PrintWriter(outputStream,true);//當第二個引數為true的時候會自動重新整理,
		//當執行println、printf 或 format 方法的時候
		
		int num=0;
		byte[] arr = new byte[100];
		while ((num = inputStream.read(arr)) != -1) {
			//列印到控制檯
			String data = new String(arr,0,num);
			System.out.println(data);
			
			//資訊回傳
			//outputStream.write(data.toUpperCase().getBytes());
			printWriter.println(data.toUpperCase());
			
			//當用戶輸入over的時候代表結束
			if (data.equals("over")) {
				break;
			}
		}
		
		serverSocket.close();
	}
}