Java網路編程
1. 獲取網路地址ip/domin
InetAddress 獲取
package com.fengye.socket.ipaddress; import java.net.InetAddress; import java.net.UnknownHostException; /** * @Description: * @Author: huang * @Date: 2021/5/5 11:30 */ public class TestInetAddress { public static void main(String[] args) throws UnknownHostException { InetAddress inetAddress = InetAddress.getByName("127.0.0.1"); InetAddress localhost = InetAddress.getByName("localhost"); InetAddress localHost = InetAddress.getLocalHost(); InetAddress deskTopName = InetAddress.getByName("DESKTOP-3POL04N"); // 本機用戶名 InetAddress bdAddress = InetAddress.getByName("www.baidu.com"); byte[] address = new byte[]{(byte) 192, (byte) 168,5,2}; InetAddress byAddress = InetAddress.getByAddress(address); System.out.println(inetAddress); // /127.0.0.1 System.out.println(localhost); // localhost/127.0.0.1 System.out.println(localHost); // DESKTOP-3POL04N/192.168.1.4 System.out.println(deskTopName); // DESKTOP-3POL04N/192.168.1.4 System.out.println(bdAddress); // www.baidu.com/39.156.66.18 System.out.println(byAddress); // /192.168.5.2 System.out.println(localhost.getAddress()); System.out.println(localhost.getCanonicalHostName()); // 獲取規范名 System.out.println(localhost.getHostAddress()); // ip System.out.println(localhost.getHostName()); // 域名 主機名 } }
2.Port 埠
-
計算機埠號用于區分不同的行程
-
計算機埠按埠號可分為3大類:
(1)公認埠:從0到1023,它們緊密系結于一些服務,通常這些埠的通訊明確表明了某種服務的協議,常用的有:http: 80 https: 443 ftp: 21 ssh: 22 telnet: 23
(2)注冊埠:從1024到49151,它們松散地系結于一些服務,也就是說有許多服務系結于這些埠,這些 埠同樣用于許多其它目的,常用的有:TomCat: 8080 MySql: 3306 Oracle:1506
(3)動態和私有埠:從49152到65535,理論上,不應為服務分配這些埠,實際上,機器通常從 1024起分配動態埠,
-
對于不同的傳輸層傳輸協議,在進行資料封裝時包頭資訊不一樣,即使UDP包和TCP包使用同一個埠,也不會導致埠沖突,
-
查看埠命令
netstat -a # netstat -ano|findstr "7024" #查看指定埠 tasklist|findstr "7024" # 查看指定埠行程
InetSocketAddress
package com.fengye.socket.socketaddress; import java.net.InetSocketAddress; /** * @Description: * @Author: huang * @Date: 2021/5/5 11:42 */ public class TestInetSocketAddress { public static void main(String[] args) { InetSocketAddress localhost = new InetSocketAddress("192.168.1.4", 8080); // ip/主機+創建埠物件 System.out.println(localhost.getAddress()); // /192.168.1.4 System.out.println(localhost.getHostName()); // DESKTOP-3POL04N System.out.println(localhost.getPort()); // 獲得埠號 8080 System.out.println(localhost.getHostString()); // DESKTOP-3POL04N } }
3.通信協議
傳輸層通信協議
-
TCP:面向連接
-
UDP:非面向連接
4.TCP編程實作
Java語言的基于套接字編程分為服務端編程和客戶端編程,其通信模型如圖所示:

4.1.TCP編程簡單C/S通信示例
1、客戶端Socket的作業程序包含以下四個基本的步驟:
創建 Socket:根據指定服務端的 IP 地址或埠號構造 Socket 類物件,若服務器端回應,則建立客戶端到服務端的通信路線,若連接失敗,則會出現例外,
打開連接到 Socket 的輸入/出流: 使用 getInputStream()方法獲得輸入流,使用 getOutputStream()方法獲得輸出流,進行資料傳輸
按照一定的協議對 Socket 進行讀/寫操作:通過輸入流讀取服務器放入線路的資訊(但不能讀取自己放入路線的資訊),通過輸出流將資訊寫入執行緒
/** * @Description: * @Author: huang * @Date: 2021/5/5 11:56 */ public class TestTcpClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost", 8888); OutputStream outputStream = socket.getOutputStream(); outputStream.write("你好,我是機器人小愛,正在為你轉接人工服務通信,建立連接中,,,".getBytes(StandardCharsets.UTF_8)); if (outputStream != null) { outputStream.close(); } if (socket != null) { socket.close(); } } }
2、服務器(服務端)程式的作業程序包含以下四個基本的步驟:
呼叫 ServerSocket(int port) :創建一個服務器端套接字,并系結到指定埠 上,用于監聽客戶端的請求,
呼叫 accept():監聽連接請求,如果客戶端請求連接,則接受連接,回傳通信 套接字物件,
呼叫該Socket類物件的 getOutputStream() 和 getInputStream ():獲取輸出 流和輸入流,開始網路資料的發送和接收,
/** * @Description: * @Author: huang * @Date: 2021/5/5 12:09 */ public class TestTcpServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("連接建立中"); Socket clientSocket = serverSocket.accept(); System.out.println("與"+clientSocket.getInetAddress()+"成功建立連接"); InputStream inputStream = clientSocket.getInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len=0; while ((len=inputStream.read(buffer))!=-1){ out.write(buffer,0,len); System.out.println(out.toString()); } if(out!=null) out.close(); if (inputStream!=null) inputStream.close(); if (clientSocket!=null) clientSocket.close(); if (serverSocket!=null) serverSocket.close(); } }
4.2.TCP編程實作C/S檔案傳輸
Server:
package com.fengye.socket.tcp; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; /** * @Description: 服務端負責接收檔案 * @Author: huang * @Date: 2021/5/5 12:22 */ public class TestTcpFileTransportServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(4396); Socket socket = serverSocket.accept(); InputStream inputStream = socket.getInputStream(); byte[] bufferFile = new byte[1024]; int len; File received = new File("E:\\Workspaces\\Java\\JavaSocket\\src\\com\\fengye\\socket\\tcp\\images\\test.png"); FileOutputStream output = new FileOutputStream(received); while ((len=inputStream.read(bufferFile))!=-1){ output.write(bufferFile,0,len); } // 接受完畢,告知客戶斷開連接 OutputStream outputStream = socket.getOutputStream(); outputStream.write("接收成功".getBytes(StandardCharsets.UTF_8)); output.close(); inputStream.close(); socket.close(); serverSocket.close(); } }
Client:
package com.fengye.socket.tcp; import java.io.*; import java.net.Socket; /** * @Description: 客戶端向服務端傳送檔案 * @Author: huang * @Date: 2021/5/5 12:17 */ public class TestTcpFileTransportClient { public static void main(String[] args) throws IOException { // 創建socket Socket socket = new Socket("localhost",4396); // 創建流 OutputStream outputStream = socket.getOutputStream(); // 讀取檔案 File file = new File("E:\\Workspaces\\Java\\JavaSocket\\src\\com\\fengye\\socket\\tcp\\images\\img.png"); byte[] buffer = new byte[1024]; // 檔案輸入流 FileInputStream fileInputStream = new FileInputStream(file); // 寫入流 int len; while ((len=fileInputStream.read(buffer))!=-1){ outputStream.write(buffer); } // 檔案傳輸結束,關閉輸出 socket.shutdownOutput(); InputStream inputStream = socket.getInputStream(); byte buffer2[] = new byte[20]; ByteArrayOutputStream msg = new ByteArrayOutputStream(); while ((len=inputStream.read(buffer2))!=-1){ msg.write(buffer2,0,len); } System.out.println(msg); msg.close(); inputStream.close(); fileInputStream.close(); outputStream.close(); socket.close(); } }
5.UDP 編程
1、類DatagramSocket 和 DatagramPacket 實作了基于 UDP 協議網路程式,
2、UDP資料報通過資料報套接字 DatagramSocket 發送和接收,系統不保證 UDP資料報一定能夠安全送到目的地,也不能確定什么時候可以抵達,
3、DatagramPacket 物件封裝了UDP資料報,在資料報中包含了發送端的IP地址和埠號以及接收端的IP地址和埠號,
4、UDP協議中每個資料報都給出了完整的地址資訊,因此無須建立發送方和接收方的連接,如同發快遞包裹一樣,
UDP網路通信流程
1、DatagramSocket與DatagramPacket
2、建立發送端,接收端
3、建立資料包
4、呼叫Socket的發送、接收方法
5、關閉Socket
接收方:
package com.fengye.socket.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class TestUdpGet { public static void main(String[] args) throws IOException { //開放埠 DatagramSocket socket = new DatagramSocket(2200); while (true){ //接收資料 byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length); socket.receive(packet); //阻塞接收 System.out.println(packet.getAddress().getHostAddress()); String msg = new String(packet.getData(), 0, packet.getLength()); if (msg.equals("shutdown")){ System.out.println("Connection has been closed"); socket.close(); return; } System.out.println(msg); } } }
發送方
package com.fengye.socket.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.nio.charset.StandardCharsets; import java.util.Scanner; public class TestUdpSend { public static void main(String[] args) throws IOException { //建立一個socket DatagramSocket socket = new DatagramSocket(1111); Scanner reader = new Scanner(System.in); while (true){ String data = reader.nextLine(); byte[] msgBytes = data.getBytes(StandardCharsets.UTF_8); InetAddress localhost = InetAddress.getByName("localhost"); DatagramPacket datagramPacket = new DatagramPacket(msgBytes, 0, msgBytes.length, localhost, 2200); socket.send(datagramPacket); if (data.equals("shutdown")){ System.out.println("Connection is closed "); reader.close(); socket.close(); return; } } } }
多執行緒實作聊天功能
package com.fengye.socket.udp.threadchat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; import java.nio.charset.StandardCharsets; /** * @Description: 訊息發送方執行緒 * @Author: huang * @Date: 2021/5/5 13:14 */ public class MsgSender implements Runnable{ private String destinationAddress; private int destinationPort; DatagramSocket socket = null; BufferedReader reader = null; public MsgSender(int sourcePort, int destinationPort, String destinationAddress) throws SocketException { this.destinationAddress = destinationAddress; this.destinationPort = destinationPort; this.socket = new DatagramSocket(sourcePort); this.reader = new BufferedReader(new InputStreamReader(System.in)); } @Override public void run() { while (true){ try { String data = reader.readLine(); byte[] dataByte = data.getBytes(StandardCharsets.UTF_8); DatagramPacket packet = new DatagramPacket(dataByte,0,dataByte.length, new InetSocketAddress(destinationAddress, destinationPort)); socket.send(packet); if(data.equals("shutdown")){ reader.close(); socket.close(); return; } } catch (IOException e) { e.printStackTrace(); } } } }
package com.fengye.socket.udp.threadchat; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; /** * @Description: 訊息接收方執行緒 * @Author: huang * @Date: 2021/5/5 13:23 */ public class MsgReceiver implements Runnable{ private int port; private String msgSeeder; DatagramSocket socket = null; public MsgReceiver(int port, String msgSeeder) throws SocketException { this.port = port; this.msgSeeder = msgSeeder; socket = new DatagramSocket(port); } @Override public void run() { while (true){ try { byte[] msgBuffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(msgBuffer,0,msgBuffer.length); socket.receive(packet); byte[] data =https://www.cnblogs.com/yif0118/p/ packet.getData(); String msg = new String(data,0, packet.getLength()); if (msg.equals("shutdown")) { socket.close(); return; } System.out.println(msgSeeder+": "+msg); } catch (IOException e) { e.printStackTrace(); } } } }
/** * @Description: 發送目的埠和監聽訊息埠必須一致 * @Author: huang * @Date: 2021/5/5 13:27 */ public class TestClient01 { public static void main(String[] args) throws SocketException { new Thread(new MsgSender(1233, 8888,"localhost")).start(); new Thread(new MsgReceiver(8888,"T1客戶端")).start(); } }
public class TestClient02 { public static void main(String[] args) throws SocketException { new Thread(new MsgSender(1234, 8800,"localhost")).start(); new Thread(new MsgReceiver(8800,"T2客戶端")).start(); } }
6.URL 編程
url:統一資源定位符
格式:<協議>://<主機><埠>/<路徑>
package com.fengye.socket.url; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class TestUrl { public static void main(String[] args) throws IOException { // 1.資源地址 URL url = new URL("http://music.163.com/song/media/outer/url?id=1403528956.mp3"); // 2.url決議 System.out.println(url.getProtocol()); // 協議 System.out.println(url.getHost()); // 主機 System.out.println(url.getPort()); // 埠 System.out.println(url.getPath()); System.out.println(url.getFile()); System.out.println(url.getQuery()); // 引數 System.out.println(url.getAuthority()); System.out.println(url.getContent()); // 內容 // 3.連接資源url HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream stream = urlConnection.getInputStream(); // 4. 檔案輸出流到 test.mp3 FileOutputStream outputStream = new FileOutputStream("test.mp3"); byte[] bytes = new byte[1024]; int len; while ((len=stream.read(bytes))!=-1){ outputStream.write(bytes,0,len); } // 5.下載完畢關閉流和url連接 stream.close(); outputStream.close(); urlConnection.disconnect(); } }
參考博文:
Java網路編程
本博客涉及示例代碼均已上傳至GitHub地址:
JavaSocket
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/283012.html
標籤:Java
上一篇:SpringBoot使用Mybatis&Mybatis-plus檔案映射配置
下一篇:Mybatis的快取
