網絡通訊,UDP.TCP協議
網絡通訊
計算機網絡
是指將地理位置不一樣的具備獨立功能的多臺計算機及其外部設備,經過通訊線路鏈接起來,在網絡操做系統,網絡管理軟件及網絡通訊協議的管理和協調下,實現資源共享和信息傳遞的計算機系統。
網絡編程
就是用來實現網絡互連的不一樣計算機上運行的程序間能夠進行數據交換。
java
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳編程
網絡通訊三要素
IP地址:InetAddress
網絡中設備的標識,不易記憶,可用主機名
端口號
用於標識進程的邏輯地址,不一樣進程的標識
傳輸協議
通信的規則
常見協議:TCP,UDP
數組
IP地址
要想讓網絡中的計算機可以互相通訊,必須爲每臺計算機指定一個標識號,經過這個標識號來指定要接受數據的計算機和識別發送的計算機,在TCP/IP協議中,這個標識號就是IP地址。服務器
// ip地址對象 // 不能經過構造方法建立 // 根據名字返回第一個全部符合要求的IP地址對象 InetAddress byName = InetAddress.getByName("PC201501241736"); //System.out.println(byName); //這個方法也能夠經過ip獲取(將ip當作name填入) //若是經過這種方式獲取ip對象 那麼不能獲取計算機名 InetAddress byName2 = InetAddress.getByName("4B5MYUK5PQ2WSNI"); //System.out.println(byName2); //返回指定ip對象表明 的計算機名 System.out.println(byName.getHostName()); //返回指定ip對象表明 的計算機IP地址 System.out.println(byName.getHostAddress());
端口號
物理端口 網卡口
邏輯端口 咱們指的就是邏輯端口
A:每一個網絡程序都會至少有一個邏輯端口
B:用於標識進程的邏輯地址,不一樣進程的標識
C:有效端口:065535,其中01024系統使用或保留端口。
經過dom命令 netstat -ano能夠查看全部佔用的端口
網絡
通訊協議
UDPdom
將數據源和目的封裝成數據包中,不須要創建鏈接;每一個數據報的大小在限制在64k;因無鏈接,是不可靠協議;不須要創建鏈接,速度快socket
數據報協議:將發送的數據分割爲指定大小後發送,無需鏈接接受端,發送端只管發送數據,不管接收端是否接收都會發送tcp
TCP
創建鏈接,造成傳輸數據的通道;在鏈接中進行大數據量傳輸;經過三次握手完成鏈接,是可靠協議;必須創建鏈接,效率會稍低
ide
數據鏈接協議:數據的發送與接收創建在鏈接通道的基礎上,客戶端鏈接服務端後才能夠發送接受請求數據大數據
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳
Socket
Socket套接字:
網絡上具備惟一標識的IP地址和端口號組合在一塊兒才能構成惟一能識別的標識符套接字。
Socket原理機制:
通訊的兩端都有Socket。
網絡通訊其實就是Socket間的通訊。
數據在兩個Socket間經過IO傳輸。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳
使用UDP協議完成數據的發送與接收
發送端思路
1:創建udp的socket服務(建立DatagramSocket對象,發送端無需指定端口)
2:將要發送的數據封裝成數據包(建立DatagramPacket對象,傳入數據字節數組,數據長度,ip地址對象,接收方接收端口號,將數據格式化)
3:經過udp的socket服務,將數據包發送出(使用DatagramSocket對象的send方法發送數據包)
4:關閉資源(DatagramSocket對象的close方法)
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; //使用socket 與udp協議實現發送代碼的書寫 public class UdpSend { public static void main(String[] args) throws IOException { // 1:創建udp的socket服務 DatagramSocket ds = new DatagramSocket(); // 建立使用udp發送數據的socket對象 發送數據使用隨機空閒端口 // DatagramSocket ds1 = new DatagramSocket(10000); // 建立使用udp發送數據的socket對象 發送數據使用指定端口 若端口被佔用會報錯 // 2:將要發送的數據封裝成數據包 // (1)準備要發送的數據(數據在網絡傳輸本質字節流) byte[] bytes = "udp發送數據".getBytes(); // (2)建立數據包對象 將數據進行格式化 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 10000); // 分別傳入數據 數據長度 接受地址對象 接受端口號 // 3:經過udp的socket服務,將數據包發送出 ds.send(dp); // 4:關閉資源 ds.close(); } }
接收端思路
1:創建udp的socket服務(建立DatagramSocket對象,接收端須要根據發送端指定端口號) 2:建立接受數據包對象(建立Datagrampacket對象,傳入每次接受字節數組以及字節數組長度) 3:經過receive方法接收數據,將收到的數據存儲到數據包對象中(調用DatagramSocket對象receive阻塞方法傳入Datagrampacket對象) 4:經過數據包對象的功能來完成對接收到數據進行解析.(獲取發送方發送時傳在數據包中定義的數據信息) 5:能夠對資源進行關閉
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; //使用socket udp協議完成數據的接收 public class UdpReceipt { public static void main(String[] args) throws IOException { // 1:創建udp的socket服務 DatagramSocket ds = new DatagramSocket(10000); // 2:經過receive方法接收數據 // (1)建立保存數據的數據包對象 byte[] b = new byte[1024];// 建立接受的字節數組 DatagramPacket dp = new DatagramPacket(b, b.length); //使用字節數組接受數據並存儲至數據包中 //(2)使用數據包對象接受數據 ds.receive(dp); //receive是阻塞方法,與scanner的獲取數據相似 //當程序執行到這個方法時會暫停運行,當接收到發送端發送的數據後繼續執行 // 3:將收到的數據存儲到數據包對象中 // 4:經過數據包對象的功能來完成對接收到數據進行解析. InetAddress address = dp.getAddress();//獲取請求地址對象 int port = dp.getPort();//獲取請求端口 byte[] data = dp.getData();//獲取存儲數據的字節數組 int length = dp.getLength();//獲取數據實際長度 System.out.println(address); System.out.println(port); System.out.println(new String(data, 0, length)); // 5:能夠對資源進行關閉 ds.close(); } }
使用UDP完成一對一信息的發送與接收
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.util.Scanner; //使用udp協議完成客戶端(既能發送也能接收)書寫 public class UdpClient { public static void main(String[] args) { // 建立多個線程分別執行發送與接收 // 接收端線程 new Thread(new Runnable() { @Override public void run() { // 建立udp協議接收端socket對象 try { DatagramSocket ds = new DatagramSocket(10000); // 建立接受數據的數據包對象 byte[] b = new byte[1024]; DatagramPacket dp = new DatagramPacket(b, b.length); // 調用阻塞方法獲取請求數據並使用數據包對象接收 while (true) { ds.receive(dp); // 從數據包對象中解析發送的數據 byte[] data = dp.getData();// 數據的字節數組 String hostAddress = dp.getAddress().getHostAddress();// 請求方ip System.out.println(hostAddress + ":" + new String(data, 0, data.length)); } } catch (Exception e) { e.printStackTrace(); } } }).start(); // 發送到線程 new Thread(new Runnable() { @Override public void run() { Scanner sc = new Scanner(System.in); try { // 建立發送端scocket對象 DatagramSocket ds = new DatagramSocket(); while (true) { System.out.println("請輸入 接收端ip:發送內容"); String str = sc.nextLine(); String[] split = str.split(":"); // 建立數據包對象並將數據字節數組傳入 byte[] b = split[1].getBytes(); DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress.getByName(split[0]), 10000); // 將數據包對象發送至指定接收端 ds.send(dp); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } }
使用TCP協議完成數據的發送與接收
接收端(服務器)思路
首先進行接收端的書寫,tcp協議創建在鏈接之上,若是發送端沒有鏈接到服務端則會報錯
1:創建服務器端的socket服務(new ServerSocket(端口))
2:服務端沒有直接流的操做,而是經過accept方法獲取客戶端對象,在經過獲取到的客戶端對象的流和客戶端進行通訊(獲取鏈接服務器的客戶端socket對象)
3:經過客戶端的獲取流對象的方法,讀取數據或者寫入數據(使用getinputStream方法獲取輸入流讀取數據)
4:若是服務完成,須要關閉客戶端,而後關閉服務器,可是,通常會關閉客戶端,不會關閉服務器,由於服務端是一直提供服務的
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; //tcp服務器端(接收端) public class TcpService { public static void main(String[] args) throws Exception { // 1:創建服務器端的socket服務,須要一個端口 ServerSocket ss = new ServerSocket(10000); // 2:服務端沒有直接流的操做,而是經過accept方法獲取客戶端對象,在經過獲取到的客戶端對象的流和客戶端進行通訊 Socket s = ss.accept();// 獲取當前鏈接服務端的客戶端對象 // 3:經過客戶端的獲取流對象的方法,讀取數據或者寫入數據 String hostAddress = s.getInetAddress().getHostAddress(); System.out.println(hostAddress + "鏈接服務器"); InputStream is = s.getInputStream(); byte[] b = new byte[1024]; int len = 0; while ((len = is.read(b)) != -1) { System.out.println(new String(b, 0, len)); } // 4:若是服務完成,須要關閉客戶端,而後關閉服務器,可是,通常會關閉客戶端,不會關閉服務器,由於服務端是一直提供服務的 s.close();// 關閉客戶端 ss.close();// 關閉服務器端 } }
發送端(客戶端)思路
發送端實際上是將數據封裝至發送端socket對象中,而後將socket對象發送至接收端進行接收
1:創建客戶端的Socket服務,並明確要鏈接的服務器。(new)
2:若是鏈接創建成功,就代表,已經創建了數據傳輸的通道.就能夠在該通道經過IO進行數據的讀取和寫入.該通道稱爲Socket流,Socket流中既有讀取流,也有寫入流.
3:經過Socket對象的方法,能夠獲取這兩個流
4:經過流的對象能夠對數據進行傳輸
5:若是傳輸數據完畢,關閉資源
import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; //tcp客戶端(發送端) public class TcpClient { public static void main(String[] args) throws Exception { // 1:創建客戶端的Socket服務,並明確要鏈接的服務器。 Socket s = new Socket("172.16.1.100", 10000); // 2:若是鏈接創建成功,就代表,已經創建了數據傳輸的通道.就能夠在該通道經過IO進行數據的讀取和寫入.該通道稱爲Socket流,Socket流中既有讀取流,也有寫入流. // 3:經過Socket對象的方法,能夠獲取這兩個流 OutputStream os = s.getOutputStream(); // 4:經過流的對象能夠對數據進行傳輸 os.write("hello".getBytes()); // 5:若是傳輸數據完畢,關閉資源 os.flush(); os.close(); s.close(); } }