UDP-TCP
一.網絡相關基本概念
1.網絡通信協議:是一種網絡通用語言,為連接不同操作系統和不同硬件體系結構的互聯網絡引提供通信支持,是一種網絡通用語言.通信協議的具體種類有很多,主要有:UDP協議和T CP協議
2.UDP 協議:是 User Datagram Protocol 的簡稱, 中文名是‘用戶數據報協議‘.是一種無連接的協議。傳輸效率很高;數據不安全,容易丟失;
特點:
1:面向無連接;
2:效率高;
3:不安全;
3.TCP/IP 協議:Transmission Control Protocol/Internet Protocol 的簡寫,中譯名為‘傳輸控制協議/因特網互聯協議‘;
特點:
1:面向連接;(客戶端和服務器需要事先建立起連接,才能通信,3次握手)
2:效率低;
3:數據安全;
4.網絡協議數據傳輸流程:從下至上:鏈路層--網絡層--傳輸層--應用層
鏈路層:軟件驅動與硬件接口;
網絡層:數據的分組與處理,IP 地址,端口號;
傳輸層:網絡通信協議的核心,數據通過網絡進行傳輸;
應用層:應用級軟件,主要進行數據的解析;
5.IP 地址:是網絡中的參與者的唯一身份標識.包含 IPV4/IPV6. IPV4 使用4個字節表示IP地址;每個字節的範圍只能是 0-255 之間.
6.端口號:是電腦中用於識別不同進程;用2個字節表示一個端口號,能表示的範圍 0-65535(2^16=65536);其中 0-1024 端口號已經被計算機的核心服務占用了,建議程序員使用1024之後
的端口號.
二.InetAddress 類(java.net)
介紹:InetAddress是java編寫的一個類,用於描述計算機的ip地址;
構造方法:InetAddress構造方法不能直接使用,因此必須通過靜態方法,獲取對象:
繼承關系:java.lang.Object--java.net.InetAddress
定義:public class InetAddress extends Object implements Serializable
靜態方法:
public static InetAddress getByName(String host){}:在給定主機名的情況下確定主機的 IP 地址
public static InetAddress getLocalHost() throws UnknownHostException{}:返回本地主機
常用方法:
public String getHostAddress(){}:返回 IP 地址字符串(以文本表現形式)
public String getHostName(){}:獲取此 IP 地址的主機名
代碼演示:
1 import java.net.InetAddress; 2 import java.net.UnknownHostException; 3 public class NetDemo{ 4 public static void main(String[] args){ 5 //獲取本地主機,返回InetAddress對象 6 InetAddress host = null; 7 try{ 8 host = InetAddress.getLocalHost(); 9}catch(UnknownHostException e){ 10 e.printStackTrace(); 11 } 12 System.out.println(host); 13 14 //獲取本地主機名 15 String name = host.getHostName(); 16 //獲取本地ip 17 String ip = host.getHostAddress(); 18 System.out.println("計算機名:"+name+";ip為:"+ip); 19 20 //通過別人的計算機名,獲取別人計算機的IP 21 try{ 22 host = InetAddress.getByName("LWL"); 23 }catch(UnknownHostException e){ 24 e.printStackTrace(); 25 } 26 String ip1 = host.getHostAddress(); 27 System.out.println(ip1); 28 } 29 }
二.UDP 常用類
1.DatagramPacket 類(java.net)
繼承關系:java.lang.Object--java.net.DatagramPacket
定義:public final class DatagramPacket extends Object
構造方法:
DatagramPacket(byte[] buf, int length, InetAddress address, int port):構造數據報包,用來將長度為 length 的包發送到指定主機上的指定端口號。
Buf:數組,用於保存要發送的數據;
Length:要發送的數據的長度;
Address:接收者的ip地址對象;
Port:接收者的端口號;
(這個對象用在發送端).
DatagramPacket(byte[] buf, int length):構造 DatagramPacket,用來接收長度為 length 的數據包。
Buf:發送者發送的數據將會保存到buf數組中;
Length:表示這個DatagramPacket對象的數組,有多少個位置可以使用;
(這個對象用在接收端).
常用主法:
public byte[] getData(){}:Returns the data buffer. The data received or the data to be sent starts from the offset in the buffer, and runs for length
long.
public int getLength(){}: Returns the length of the data to be sent or the length of the data received.
2.DatagramSocket 類(java.net)
繼承關系:java.lang.Object--java.net.DatagramSocket
定義:public class DatagramSocket extends Object implements Closeable
構造方法:
DatagramSocket() throws SocketException:構造數據報套接字並將其綁定到本地主機上任何可用的端口。
(一般將該對象用在發送端,可以通過該對象,將數據報包對象發送出去)
DatagramSocket(int port) : 創建數據報套接字並將其綁定到本地主機上的指定端口。(一般用在接收端,監聽指定的端口號,可以接收別人向該端口發送的數據報包)
常用方法:
public void send(DatagramPacket p) throws IOException{}:從此套接字發送數據報包
public void receive(DatagramPacket p) throws IOException{}:從此套接字接收數據報包。
該方法有線程阻塞的效果,因此必須在接收端先調用該方法,發送端才能發數據報包,否則會丟失數據報包
3.UDP通信案例
1 //UDP通信實現:Receiver 2 import java.net.DatagramPacket; 3 import java.net.DatagramSocket; 4 5 public class UDPReceiver { 6 public static void main(String[] args) throws Exception { 7 // 準備用於接收的數據報包對象 8 byte[] b = new byte[1024]; 9 DatagramPacket dp = new DatagramPacket(b, b.length); 10 // 創建接收端對象 11 DatagramSocket ds = new DatagramSocket(8891); 12 // 接收端使用自己的數據報包對象接收發送過來的數據 13 ds.receive(dp); 14 // 獲取數組和有效長度 15 byte[] bs = dp.getData(); 16 int i = dp.getLength(); 17 // 轉字符串 18 String s = new String(bs, 0, i); 19 System.out.println("發送端說:" + s); 20 ds.close(); 21 } 22 }
1 //UDP通信實現:sender 2 import java.net.DatagramPacket; 3 import java.net.DatagramSocket; 4 import java.net.InetAddress; 5 import java.util.Scanner; 6 7 public class UDPSender { 8 public static void main(String[] args) throws Exception { 9 // 提示發送者輸入發送消息 10 Scanner sc = new Scanner(System.in); 11 System.out.println("請輸入要發送的消息::"); 12 String message = sc.next(); 13 14 // 將輸入的消息轉化成字節數組 15 byte[] b = message.getBytes(); 16 // 將原始數據封裝成DatagramPacket對象 17 DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress.getLocalHost(), 8891); 18 // 創建發送端對象 19 DatagramSocket ds = new DatagramSocket(); 20 // 使用發送端對象將封裝的DatagramPacket對象發送出去 21 ds.send(dp); 22 // 關閉流 23 ds.close(); 24 } 25 }
三.TCP 常用類
1.Socket
介紹:用於表示客戶端的一個類.TCP 協議中客戶端和服務器的交互是通過IO流完成的,而所有的 IO 流對象都是客戶端提供的!
繼承關系:java.lang.Object--java.net.Socket
定義:public class Socket extends Object implements Closeable
構造方法:
Socket(String host, int port) throws UnknownHostException,IOException :創建一個流套接字並將其連接到指定主機上的指定端口號。如果該客戶端對象能創建成功,說明3次握手已經成功了!
2.ServerSocket
介紹:用於表示服務端的一個類
繼承關系:java.lang.Object--java.net.ServerSocket
定義:public class ServerSocket extends Object implements Closeable
構造方法:
ServerSocket(int port) throws IOException : 創建綁定到特定端口的服務器套接字。實際開發中先有服務器對象,才會有客戶端去訪問;因此創建服務器對象的人,可以自己指定一個端口號;
常用方法:
public Socket accept() throws IOException{}: 偵聽並接受到此套接字的連接。該方法有線程阻塞的效果,如果沒有客戶端訪問該服務器,那麽該服務器的當前線程將一直阻塞
3.TCP 通信案例
1 //客戶端 2 import java.io.IOException; 3 import java.io.OutputStream; 4 import java.net.Socket; 5 import java.net.UnknownHostException; 6 import java.util.Scanner; 7 8 public class TCPClientDemo { 9 public static void main(String[] args) throws UnknownHostException, 10 IOException { 11 // 創建客戶端對象 12 Socket s = new Socket("127.0.0.1", 9999); 13 // 面對客戶端對象獲取網絡中的輸出流 14 OutputStream out = s.getOutputStream(); 15 // 向網絡中寫入數據 16 Scanner sc = new Scanner(System.in); 17 System.out.println("請輸入要發送的消息:"); 18 String str = sc.next(); 19 20 out.write(str.getBytes()); 21 } 22 }
1 //服務器端 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 7 public class TCPReceiverDemo { 8 public static void main(String[] args) throws IOException { 9 // 創建服務器端對象 10 ServerSocket ss = new ServerSocket(9999); 11 12 // 讓服務器端對象等待客戶端連接 accept 13 Socket s = ss.accept(); 14 15 // 面向Socket對象,獲取輸入流對象 16 InputStream in = s.getInputStream(); 17 18 // 一次讀完 19 byte[] b = new byte[1024]; 20 int i = in.read(b); 21 22 // 轉換成字符串輸出 23 String str = new String(b, 0, i); 24 System.out.println("客戶端發來消息:" + str); 25 } 26 }
4.文件上傳案例--多線程版
1 /* 2 文件上傳服務器端 多線程 3 */ 4 import java.io.FileOutputStream; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.net.ServerSocket; 8 import java.net.Socket; 9 public class FileloadServer { 10 public static void main(String[] args) throws Exception { 11 // 創建服務器端對象 12 ServerSocket ss = new ServerSocket(8870); // throws IOException 13 // 監聽端口,形成阻塞狀態 14 while (true) { 15 final Socket s = ss.accept();// throws IOException 16 new Thread() { 17 @Override 18 public void run() { 19 try { 20 // 我是服務器中的程序,我要創建一個本地網絡輸入流 21 InputStream in = s.getInputStream(); 22 // 我是服務器中的程序,我要將網絡輸入流中的內容寫入本地磁盤(位置如何確定?) 23 FileOutputStream fout = new FileOutputStream(System.currentTimeMillis() + ".jpg"); 24 int i = -1; 25 byte[] b = new byte[1024]; 26 while ((i = in.read(b)) != -1) { 27 fout.write(b, 0, i); // 寫入本地磁盤 28 } 29 // 通知客戶端上傳成功,建立網絡輸出流 30 OutputStream out = s.getOutputStream(); 31 out.write("上傳成功".getBytes()); 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } 35 } 36 }.start(); 37 } 38 } 39 }
1 /* 2 上傳文件客戶端 3 */ 4 import java.io.FileInputStream; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.net.Socket; 8 public class FileUploadClient { 9 public static void main(String[] args) throws Exception { 10 // 創建客戶端對象 11 Socket s = new Socket("127.0.0.1", 8870);// throws UnknownHostException,IOException 12 // 創建本地文件的輸入流 我是程序,我現在讀取本地文件,創建字節輸入流 13 FileInputStream fin = new FileInputStream("E:\\JAVAPractice\\net\\1.jpg");// throws FileNotFoundException 14 // 面向客戶端 獲取輸出流,向網絡中寫入 15 OutputStream out = s.getOutputStream(); // throws IOException 16 // 循環 寫入網絡 17 int i = -1; 18 byte[] b = new byte[1024]; 19 while ((i = fin.read(b)) != -1) { 20 out.write(b, 0, i); 21 } 22 // 通知服務器端循環輸出完成--解決死鎖問題 23 s.shutdownOutput(); // throws IOException 24 // 若文件上傳完成,服務器要通知我,我要接收這個消息,因此創建網絡輸入流,並打印在控制臺上 25 InputStream in = s.getInputStream();// throws IOException 26 i = in.read(b); 27 String message = new String(b, 0, i);// Throws IndexOutOfBoundsException 28 System.out.println("消息來自服務端:" + message); 29 } 30 }
UDP-TCP