Java網絡編程技術TCP和UDP
網絡編程概述
網絡編程就是兩個或多個設備之間的數據交換,其實更具體的說,網絡編程就是兩個或多個程序之間的數據交換,和普通的單機程序相比,網絡程序最大的不同就是需要交換數據的程序運行在不同的計算機上,這樣就造成了數據交換的復雜 。
網絡通訊的過程網絡通訊基于“請求-響應”模型
C/S結構
B/S結構
P2P程序
協議(Protocol)網絡編程中最重要,也是最復雜的概念
在現有的網絡中,網絡通訊的方式主要有兩種
TCP(傳輸控制協議)方式
UDP(用戶數據報協議)方式
在網絡通訊中,TCP方式就類似于撥打電話,使用該種方式進行網絡通訊時,需要建立專門的虛擬連接,然后進行可靠的數據傳輸,如果數據發送失敗,則客戶端會自動重發該數據。而UDP方式就類似于發送短信,使用這種方式進行網絡通訊時,不需要建立專門的虛擬連接,傳輸也不是很可靠,如果發送失敗則客戶端無法獲得 。
這兩種傳輸方式都是實際的網絡編程中進行使用,重要的數據一般使用TCP方式進行數據傳輸,而大量的非核心數據則都通過UDP方式進行傳遞,在一些程序中甚至結合使用這兩種方式進行數據的傳遞 。
TCP需要建立專用的虛擬連接以及確認傳輸是否正確,所以使用TCP方式的速度稍微慢一些,而且傳輸時產生的數據量要比UDP稍微大一些 。
UDP是無連接通信協議,即在數據傳輸時,數據的發送端和接收端不建立邏輯連接。簡單來說,當一臺計算機向另外一臺計算機發送數據時,發送端不會確認接收端是否存在,就會發出數據,同樣接收端在收到數據時,也不會向發送端反饋是否收到數據。 ? ? 由于使用UDP協議消耗資源小,通信效率高,所以通常都會用于音頻、視頻和普通數據的傳輸,例如視頻會議都使用UDP協議,因為這種情況即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。 ? ? 但是在使用UDP協議傳送數據時,由于UDP的面向無連接性,不能保證數據的完整性,因此在傳輸重要數據時不建議使用UDP協議 。
TCP協議是面向連接的通信協議,即在傳輸數據前先在發送端和接收端建立邏輯連接,然后再傳輸數據,它提供了兩臺計算機之間可靠無差錯的數據傳輸。在TCP連接中必須要明確客戶端與服務器端,由客戶端向服務端發出連接請求,每次連接的創建都需要經過“三次握手”。第一次握手,客戶端向服務器端發出連接請求,等待服務器確認,第二次握手,服務器端向客戶端回送一個響應,通知客戶端收到了連接請求,第三次握手,客戶端再次向服務器端發送確認信息,確認連接 。
由于TCP協議的面向連接特性,它可以保證傳輸數據的安全性,所以是一個被廣泛采用的協議,例如在下載文件時,如果數據接收不完整,將會導致文件數據丟失而不能被打開,因此,下載文件時必須采用TCP協議 。
網絡編程步驟
客戶端網絡編程步驟
客戶端(Client)是指網絡編程中首先發起連接的程序,客戶端一般實現程序界面和基本邏輯實現,在進行實際的客戶端編程時,無論客戶端復雜還是簡單,以及客戶端實現的方式,客戶端的編程主要由三個步驟實現
建立網絡連接
客戶端網絡編程的第一步都是建立網絡連接。在建立網絡連接時需要指定連接到的服務器的IP地址和端口號,建立完成以后,會形成一條虛擬的連接,后續的操作就可以通過該連接實現數據交換了
交換數據
連接建立以后,就可以通過這個連接交換數據了。交換數據嚴格按照請求響應模型進行,由客戶端發送一個請求數據到服務器,服務器反饋一個響應數據給客戶端,如果客戶端不發送請求則服務器端就不響應。 ? 根據邏輯需要,可以多次交換數據,但是還是必須遵循請求響應模型 。
關閉網絡連接
在數據交換完成以后,關閉網絡連接,釋放程序占用的端口、內存等系統資源,結束網絡編程 。
服務端網絡編程步驟
服務器端(Server)是指在網絡編程中被動等待連接的程序,服務器端一般實現程序的核心邏輯以及數據存儲等核心功能。服務器端的編程步驟和客戶端不同,是由四個步驟實現,依次是
監聽端口
服務器端屬于被動等待連接,所以服務器端啟動以后,不需要發起連接,而只需要監聽本地計算機的某個固定端口即可 ? ? 這個端口就是服務器端開放給客戶端的端口,服務器端程序運行的本地計算機的IP地址就是服務器端程序的IP地址 。
獲得連接
當客戶端連接到服務器端時,服務器端就可以獲得一個連接,這個連接包含客戶端的信息,例如客戶端IP地址等等,服務器端和客戶端也通過該連接進行數據交換 ? ? 一般在服務器端編程中,當獲得連接時,需要開啟專門的線程處理該連接,每個連接都由獨立的線程實現 。
交換數據
服務器端通過獲得的連接進行數據交換。服務器端的數據交換步驟是首先接收客戶端發送過來的數據,然后進行邏輯處理,再把處理以后的結果數據發送給客戶端。簡單來說,就是先接收再發送,這個和客戶端的數據交換數序不同 ? ? 其實,服務器端獲得的連接和客戶端連接是一樣的,只是數據交換的步驟不同 。
關閉連接
當服務器程序關閉時,需要關閉服務器端,通過關閉服務器端使得服務器監聽的端口以及占用的內存可以釋放出來,實現了連接的關閉
Java網絡編程技術
網絡類——InetAddress類
public class IPDemo { public static void main(String[] args) { try { InetAddress inetAddress = InetAddress.getLocalHost(); System.out.println(inetAddress.toString()); System.out.println(inetAddress.getHostAddress()); System.out.println(inetAddress.getHostName()); InetAddress ia = InetAddress.getByName("localhost"); System.out.println(ia.getHostAddress()); System.out.println(ia.getHostName()); } catch (UnknownHostException e) { e.printStackTrace(); } } }
UDP編程
UDP發送端
步驟
1、建立udpsocket服務
2、提供數據,并將數據封裝到數據包中
3、通過socket服務的發送功能將數據包發送出去
4、關閉資源
public class UdpSend { public static void main(String[] args) { DatagramSocket datagramSocket = null; try { // 1、創建udp服務,通過DatagramSocket對象 datagramSocket = new DatagramSocket(8888); // 2、確定數據,并封裝到數據包 byte[] data = “Hello everyone,,guys".getBytes(); DatagramPacket datagramPacket = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.50.35"), 9999); //3、通過socket服務,將已有的數據包發送出去 datagramSocket.send(datagramPacket); } catch (Exception e) { e.printStackTrace(); } finally { // 4、關閉資源 if (datagramSocket != null) { datagramSocket.close(); } } } }
UDP接收端
步驟
1、定義udpsocket服務,通常會監聽一個端口
2、定義數據包,因為要存儲接收到的數據,數據包中有更多的功能可以提取字節數據中不同的數據信息
3、通過receive方法將接收的到的數據存入已定義好的數據包中
4、通過數據包對象特有的功能,將數據取出
5、關閉資源
public class UdpReceive { public static void main(String[] args) { DatagramSocket datagramSocket = null; try { datagramSocket = new DatagramSocket(9999); // 2、定義數據包用于存儲數據 byte[] bytes = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length); // 3、通過服務的receive方法將受到的數據存入數據包中 datagramSocket.receive(datagramPacket); // 阻塞式方法 // 4、通過數據包的方法獲取數據包中的數據 String ip = datagramPacket.getAddress().getHostAddress().toString(); // 獲取地址 String data = new String(datagramPacket.getData(), 0, datagramPacket.getLength()); int port = datagramPacket.getPort(); System.out.println(ip + "::" + data + "::" + port); } catch (Exception e) { e.printStackTrace(); } finally { if (datagramSocket != null) { datagramSocket.close(); } } } }
UDP鍵盤錄入
public class UdpSend02 { public static void main(String[] args) { DatagramSocket datagramSocket = null; try { // 1、創建udp服務,通過DatagramSocket對象 datagramSocket = new DatagramSocket(8888); // 2、確定數據,并封裝到數據包 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while ((line = bufr.readLine()) != null) { if ("bye".equals(line)) { break; } byte[] data = line.getBytes(); DatagramPacket datagramPacket = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.50.35"), 10000); //3、通過socket服務,將已有的數據包發送出去 datagramSocket.send(datagramPacket); } } } }
UDP聊天
public class Send implements Runnable { private DatagramSocket datagramSocket; public Send(DatagramSocket datagramSocket) { this.datagramSocket = datagramSocket; } @Override public void run() { try { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while ((line = bufr.readLine()) != null) { byte[] data = line.getBytes(); DatagramPacket datagramPacket = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.50.255"), 10000); datagramSocket.send(datagramPacket); if ("bye".equals(line)) { break; } } } catch (Exception e) { e.printStackTrace(); } } }
public class Receive implements Runnable { private DatagramSocket datagramSocket; public Receive(DatagramSocket datagramSocket) { this.datagramSocket = datagramSocket; } @Override public void run() { try { while (true) { byte[] bytes = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length); datagramSocket.receive(datagramPacket); String ip = datagramPacket.getAddress().getHostAddress(); String data = new String(datagramPacket.getData(), 0, datagramPacket.getLength()); System.out.println(ip + ">>>:" + data); } } catch (Exception e) { e.printStackTrace(); } } }
public class ChatDemo { public static void main(String[] args) { try { DatagramSocket sendSocket = new DatagramSocket(); DatagramSocket receiveSocket = new DatagramSocket(10000); new Thread(new Send(sendSocket)).start(); new Thread(new Receive(receiveSocket)).start(); } catch (SocketException e) { e.printStackTrace(); } } }
TCP編程
這里舉例一個圖片上傳的案例
public class TcpClient05 { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 8888); // 獲取流對象 FileInputStream fis = new FileInputStream(new File("C:\\Users\\chend\\Pictures\\picture\\washing.jpg")); OutputStream out = socket.getOutputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); int len = 0; byte[] bytes = new byte[1024]; while ((len = fis.read(bytes)) != -1) { out.write(bytes, 0, len); } socket.shutdownOutput(); String result = in.readLine(); System.out.println(result); } catch (IOException e) { e.printStackTrace(); } } }
public class TcpServer05 { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(8888); Socket socket = serverSocket.accept(); // 獲取流對象 InputStream in = socket.getInputStream(); FileOutputStream fos = new FileOutputStream(new File("E:\\DingLi\\1912.jpg")); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); int len = 0; byte[] bytes = new byte[1024]; while ((len = in.read(bytes)) != -1) { fos.write(bytes, 0, len); } out.println("圖片上傳成功!"); } catch (IOException e) { throw new RuntimeException("圖片上傳失??!"); } } }
關于java的網絡編程就說到這里了,如有不足之處,歡迎指正!
感恩能與大家在華為云遇見!希望能與大家一起在華為云社區共同成長。
TCP/IP UDP 網絡
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。