內容:java
一、網絡通訊協議編程
二、UDP與TCP數組
三、UDP通訊安全
四、TCP通訊服務器
五、網絡編程總結網絡
一、網絡通訊協議socket
(1)基本概念學習
網絡:由多臺計算機以及外部設備鏈接起來的一個系統,咱們稱之爲網絡spa
通訊協議:就像交通規則,規定網絡上傳輸的數據的格式、大小、速度等.net
在咱們如今的網絡中都有哪些通訊協議:
(2)TCP/IP
網絡通訊協議有不少種,目前應用最普遍的是TCP/IP協議(Transmission Control Protocal/Internet Protocal),
它是一個包括TCP協議和IP協議,UDP(User Datagram Protocal)協議和其它一些協議的協議組,在學習具體協議
以前首先了解一下TCP/IP協議組的層次結構。
在進行數據傳輸時,要求發送的數據與收到的數據徹底同樣,這時,就須要在原有的數據上添加不少信息,以保證數據在
傳輸過程當中的數據格式徹底一致。TCP/IP協議的層次結構比較簡單,共分爲四層,如圖所示:
上圖中,TCP/IP協議中的四層分別是應用層、傳輸層、網絡層和鏈路層,每層分別負責不一樣的通訊功能,詳細解釋:
(3)IP地址和端口號
IP地址:網絡中每一臺計算機的邏輯標識
端口號:區分計算機中的不一樣程序(0到65535)
總結:當咱們向別的計算機發送信息時咱們能夠經過IP地址找到計算機,經過端口號肯定應用程序
(4)InetAddress類使用
瞭解了IP地址的做用,咱們看學習下JDK中提供了一個InetAdderss類,該類用於封裝一個IP地址,並提供了
一系列與IP地址相關的方法,下表中列出了InetAddress類的一些經常使用方法:
上圖中,列舉了InetAddress的四個經常使用方法:
接下來經過一個案例來演示InetAddress的經常使用方法,以下所示:
1 import java.net.*; 2 3 // INetAddress實例 4 public class INetAddressDemo { 5 public static void main(String[] args) throws UnknownHostException { 6 InetAddress local = InetAddress.getLocalHost(); 7 System.out.println(local); // 打印格式: 用戶名/IP地址 8 InetAddress remote = InetAddress.getByName("www.baidu.com"); 9 10 System.out.println("本機的IP地址:" + local.getHostAddress()); 11 System.out.println("本機的主機名爲: " + local.getHostName()); 12 System.out.println("itcast的IP地址:" + remote.getHostAddress()); 13 System.out.println("itcast的主機名爲:" + remote.getHostName()); 14 } 15 }
二、UDP與TCP
(1)UDP協議
UDP協議的特色是面向無鏈接的通訊協議,不保證數據的完整性
即在數據傳輸時,數據的發送端和接收端不創建邏輯鏈接。簡單來講,當一臺計算機向另一臺計算機
發送數據時,發送端不會確認接收端是否存在,就會發出數據,一樣接收端在收到數據時,也不會向發送端
反饋是否收到數據,例如:咱們的供屏軟件。
這種協議既然有那麼多缺點爲何還用它?
因爲使用UDP協議消耗資源小,通訊效率高,因此一般都會用於音頻、視頻和普通數據的傳輸例如視頻會議
都使用UDP協議,由於這種狀況即便偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。
但在使用UDP協議傳送數據時,因爲UDP的面向無鏈接性,不能保證數據的完整性,所以在傳輸重要數據時
不建議使用UDP協議。UDP的交換過程以下圖所示。
(2)TCP協議
TCP協議的特色是面向鏈接的通訊協議,保證數據的安全和完整性
即在傳輸數據前先在發送端和接收端創建邏輯鏈接,而後再傳輸數據,它提供了兩臺計算機之間可靠無差錯的
數據傳輸。在TCP鏈接中必須要明確客戶端與服務器端,由客戶端向服務端發出鏈接請求,每次鏈接的建立都
須要通過「三次握手」。第一次握手,客戶端向服務器端發出鏈接請求,等待服務器確認,第二次握手,服務器端
向客戶端回送一個響應,通知客戶端收到了鏈接請求,第三次握手,客戶端再次向服務器端發送確認信息,確認
鏈接。整個交互過程以下圖所示:
因爲TCP協議的面向鏈接特性,它能夠保證傳輸數據的安全性,因此是一個被普遍採用的協議,例如在下載文件時,
若是數據接收不完整,將會致使文件數據丟失而不能被打開,所以,下載文件時必須採用TCP協議
三、UDP通訊
在UPD通訊中有2個經常使用的類,一個是數據包類DatagramPacket,一個是數據包發送接收器類DatagramSocket
(1)DatagramPacket類
前面介紹了UDP是一種面向無鏈接的協議,所以,在通訊時發送端和接收端不用創建鏈接。UDP通訊的過程就像是
貨運公司在兩個碼頭間發送貨物同樣。在碼頭髮送和接收貨物時都須要使用集裝箱來裝載貨物,UDP通訊也是同樣,
發送和接收的數據也須要使用「集裝箱」進行打包,爲此JDK中提供了一個DatagramPacket類,該類的實例對象就至關於
一個集裝箱,用於封裝UDP通訊中發送或者接收的數據。
想要建立一個DatagramPacket對象,首先須要瞭解一下它的構造方法。在建立發送端和接收端的DatagramPacket對象時,
使用的構造方法有所不一樣,接收端的構造方法只須要接收一個字節數組來存放接收到的數據,而發送端的構造方法不但要
接收存放了發送數據的字節數組,還須要指定發送端IP地址和端口號。
構造方法以下:
經常使用方法以下:
(2)DatagramSocket類
DatagramPacket數據包的做用就如同是「集裝箱」,能夠將發送端或者接收端的數據封裝起來。然而運輸貨物只有
「集裝箱」是不夠的,還須要有碼頭。在程序中須要實現通訊只有DatagramPacket數據包也一樣不行,爲此JDK中
提供了DatagramSocket類,DatagramSocket類的做用就相似於碼頭,使用這個類的實例對象就能夠發送和接收
DatagramPacket數據包,發送數據的過程以下圖所示:
構造方法:
經常使用方法:
(3)UDP通訊程序
大體過程以下所示:
發送端代碼:
1 import java.net.*; 2 3 /* 4 * 發送端: 5 * 1,建立DatagramSocket對象 6 * 2,建立DatagramPacket對象,並封裝數據 7 * 3,發送數據 8 * 4,釋放流資源 9 */ 10 11 public class UDPSender { 12 public static void main(String[] args) throws Exception { 13 // 1,建立DatagramSocket對象 14 DatagramSocket ds = new DatagramSocket(); 15 // 2,建立DatagramPacket對象,並封裝數據 16 // 構造數據報包,用來將長度爲 length 的包發送到指定主機上的指定端口號。 17 byte[] buffer = "hello, UDP".getBytes(); 18 InetAddress ip = InetAddress.getByName("127.0.0.1"); 19 int port = 12345; 20 DatagramPacket dp = new DatagramPacket(buffer, buffer.length, ip, port); 21 // 3,發送數據 22 ds.send(dp); 23 // 4,釋放流資源 24 ds.close(); 25 26 } 27 }
接收端代碼:
1 import java.net.*; 2 3 /* 4 * UDP接收端 5 * 6 * 1,建立DatagramSocket對象 7 * 2,建立DatagramPacket對象 8 * 3,接收數據存儲到DatagramPacket對象中 9 * 4,獲取DatagramPacket對象的內容 10 * 5,釋放流資源 11 */ 12 13 public class UDPReceiver { 14 public static void main(String[] args) throws Exception{ 15 // 1,建立DatagramSocket對象,並指定端口號 16 int port = 12345; 17 DatagramSocket ds = new DatagramSocket(port); 18 // 2,建立DatagramPacket對象, 建立一個空的倉庫 19 byte[] buffer = new byte[1024]; 20 DatagramPacket dp = new DatagramPacket(buffer, 1024); 21 // 3,接收數據存儲到DatagramPacket對象中 22 System.out.println("等待發送端發送數據..."); 23 ds.receive(dp); 24 // 4,獲取DatagramPacket對象的內容 25 InetAddress ipAddress = dp.getAddress(); 26 String ip = ipAddress.getHostAddress();// 獲取到了IP地址 27 // 發來什麼數據 getData()以及發來多少數據 getLenth() 28 byte[] data = dp.getData(); 29 int length = dp.getLength(); 30 // 顯示收到的數據 31 String dataStr = new String(data, 0, length); 32 System.out.println("IP地址:" + ip + "數據是" + dataStr); 33 // 5,釋放流資源 34 ds.close(); 35 36 } 37 }
四、TCP通訊
TCP通訊同UDP通訊同樣,都能實現兩臺計算機之間的通訊,通訊的兩端都須要建立socket對象。
區別在於,UDP中只有發送端和接收端,不區分客戶端與服務器端,計算機之間能夠任意地發送數據
而TCP通訊是嚴格區分客戶端與服務器端,在通訊時,必須先由客戶端去鏈接服務器端才能實現通訊,
服務器端不能夠主動鏈接客戶端,而且服務器端程序須要事先啓動,等待客戶端的鏈接。
在JDK中提供了兩個類用於實現TCP程序,一個是Socket類,用於表示客戶端,另外一個是ServerSocket類,用於表示服務器端。
通訊時,首先建立表明服務器端的ServerSocket對象,該對象至關於開啓一個服務,並等待客戶端的鏈接,
而後建立表明客戶端的Socket對象向服務器端發出鏈接請求,服務器端響應請求,二者創建鏈接開始通訊。
(1)ServerSocket
構造方法:
經常使用方法:
ServerSocket對象負責監聽某臺計算機的某個端口號,在建立ServerSocket對象後,須要繼續調用該對象的accept()方法,
接收來自客戶端的請求。當執行了accept()方法以後,服務器端程序會發生阻塞,直到客戶端發出鏈接請求,accept()方法
纔會返回一個Scoket對象用於和客戶端實現通訊,程序才能繼續向下執行。
(2)Socket
構造方法:
經常使用方法:
在Socket類的經常使用方法中,getInputStream()和getOutStream()方法分別用於獲取輸入流和輸出流。當客戶端和服務端創建鏈接後,
數據是以IO流的形式進行交互的,從而實現通訊。
接下來經過一張圖來描述服務器端和客戶端的數據傳輸,以下圖所示:
(3)TCP通訊程序
服務器端:
1 /* 2 * TCP 服務器端 3 * 4 * 1,建立服務器ServerSocket對象(指定服務器端口號) 5 * 2,開啓服務器了,等待客戶端的鏈接,當客戶端鏈接後,能夠獲取到鏈接服務器的客戶端Socket對象 6 * 3,給客戶端反饋信息 7 * 4,關閉流資源 8 */ 9 10 import java.io.*; 11 import java.net.*; 12 13 public class TCPServer { 14 public static void main(String[] args) throws IOException { 15 //1,建立服務器ServerSocket對象(指定服務器端口號) 16 ServerSocket ss = new ServerSocket(8888); 17 //2,開啓服務器了,等待客戶端的鏈接,當客戶端鏈接後,能夠獲取到鏈接服務器的客戶端Socket對象 18 Socket s = ss.accept(); 19 //3,給客戶端反饋信息 20 /* 21 * a,獲取客戶端的輸出流 22 * b,在服務端端,經過客戶端的輸出流寫數據給客戶端 23 */ 24 //a,獲取客戶端的輸出流 25 OutputStream out = s.getOutputStream(); 26 //b,在服務端端,經過客戶端的輸出流寫數據給客戶端 27 out.write("你已經鏈接上了服務器".getBytes()); 28 //4,關閉流資源 29 out.close(); 30 s.close(); 31 //ss.close(); 服務器流 一般都是不關閉的 32 } 33 34 }
客戶端:
1 /* 2 * TCP 客戶端 3 * 4 * 1,建立客戶端Socket對象,(指定要鏈接的服務器地址與端口號) 5 * 2,獲取服務器端的反饋回來的信息 6 * 3,關閉流資源 7 */ 8 9 import java.io.*; 10 import java.net.*; 11 12 public class TCPClient { 13 public static void main(String[] args) throws IOException { 14 // 1,建立客戶端Socket對象,(指定要鏈接的服務器地址與端口號) 15 Socket s = new Socket("127.0.0.1", 8888); 16 // 2,獲取服務器端的反饋回來的信息 17 InputStream in = s.getInputStream(); 18 // 把流中的數據存儲到數組中,並記錄讀取字節的個數 19 byte[] buffer = new byte[1024]; 20 int length = in.read(buffer); 21 // 顯示數據 22 InetAddress ip = s.getInetAddress(); 23 System.out.println(ip + new String(buffer, 0, length)); 24 // 3,關閉流資源 25 in.close(); 26 s.close(); 27 28 } 29 }
服務端和客戶端:
(4)文件上傳案例
文件上傳大體過程:
1 import java.io.*; 2 import java.net.*; 3 4 public class FileUploadServer { 5 public static void main(String[] args) throws IOException { 6 //1,建立服務器,等待客戶端鏈接 7 ServerSocket serverSocket = new ServerSocket(8888); 8 Socket clientSocket = serverSocket.accept(); 9 //顯示哪一個客戶端Socket鏈接上了服務器 10 InetAddress ipObject = clientSocket.getInetAddress();//獲得IP地址對象 11 String ip = ipObject.getHostAddress(); //獲得IP地址字符串 12 System.out.println("客戶端的IP:" + ip); 13 14 //2,獲取Socket的輸入流 15 InputStream in = clientSocket.getInputStream(); 16 //3,建立目的地的字節輸出流 17 BufferedOutputStream fileOut = new BufferedOutputStream(new FileOutputStream("D:\\upload\\" + System.currentTimeMillis() + ".jpg")); 18 //4,把Socket輸入流中的數據,寫入目的地的字節輸出流中 19 byte[] buffer = new byte[1024]; 20 int len = -1; 21 while((len = in.read(buffer)) != -1){ 22 //寫入目的地的字節輸出流中 23 fileOut.write(buffer, 0, len); 24 } 25 26 //-----------------反饋信息--------------------- 27 //5,獲取Socket的輸出流, 做用:寫反饋信息給客戶端 28 OutputStream out = clientSocket.getOutputStream(); 29 //6,寫反饋信息給客戶端 30 out.write("圖片上傳成功".getBytes()); 31 32 out.close(); 33 fileOut.close(); 34 in.close(); 35 clientSocket.close(); 36 //serverSocket.close(); 37 } 38 39 }
1 import java.io.*; 2 import java.net.*; 3 4 public class FileUploadClient { 5 public static void main(String[] args) throws IOException { 6 // 1,建立客戶端Socket,鏈接服務器 7 Socket socket = new Socket("127.0.0.1", 8888); 8 // 2,獲取Socket流中的輸出流,功能:用來把數據寫到服務器 9 OutputStream out = socket.getOutputStream(); 10 // 3,建立字節輸入流,功能:用來讀取數據源(圖片)的字節 11 BufferedInputStream fileIn = new BufferedInputStream( 12 new FileInputStream("D:\\test.jpg")); 13 // 4,把圖片數據寫到Socket的輸出流中(把數據傳給服務器) 14 byte[] buffer = new byte[1024]; 15 int len = -1; 16 while ((len = fileIn.read(buffer)) != -1) { 17 // 把數據寫到Socket的輸出流中 18 out.write(buffer, 0, len); 19 } 20 // 5,客戶端發送數據完畢,結束Socket輸出流的寫入操做,告知服務器端 21 socket.shutdownOutput(); 22 23 // -----------------反饋信息--------------------- 24 // 6,獲取Socket的輸入流 做用: 讀反饋信息 25 InputStream in = socket.getInputStream(); 26 // 7,讀反饋信息 27 byte[] info = new byte[1024]; 28 // 把反饋信息存儲到info數組中,並記錄字節個數 29 int length = in.read(info); 30 // 顯示反饋結果 31 System.out.println(new String(info, 0, length)); 32 33 // 8,關閉流 34 in.close(); 35 fileIn.close(); 36 out.close(); 37 socket.close(); 38 } 39 40 }
五、網絡編程總結
(1)基礎知識
(2)UDP程序交互的流程
發送端:
1,建立DatagramSocket對象
2,建立DatagramPacket對象,並封裝數據
3,發送數據
4,釋放流資源
接收端:
1,建立DatagramSocket對象
2,建立DatagramPacket對象
3,接收數據存儲到DatagramPacket對象中
4,獲取DatagramPacket對象的內容
5,釋放流資源
(3)TCP程序交互的流程
客戶端:
1,建立客戶端的Socket對象
2,獲取Socket的輸出流對象
3,寫數據給服務器
4,獲取Socket的輸入流對象
5,使用輸入流,讀反饋信息
6,關閉流資源
服務器端:
1,建立服務器端ServerSocket對象,指定服務器端端口號
2,開啓服務器,等待着客戶端Socket對象的鏈接,若有客戶端鏈接,返回客戶端的Socket對象
3,經過客戶端的Socket對象,獲取客戶端的輸入流,爲了實現獲取客戶端發來的數據
4,經過客戶端的輸入流,獲取流中的數據
5,經過客戶端的Socket對象,獲取客戶端的輸出流,爲了實現給客戶端反饋信息
6,經過客戶端的輸出流,寫數據到流中
7,關閉流資源