java 網路編程

来源:https://www.cnblogs.com/xiarongblogs/archive/2023/08/20/17644816.html
-Advertisement-
Play Games

# 網路編程 ## 一、概述 網路編程是指編寫運行在多個設備(電腦)的程式,這些設備都通過網路連接起來。 ### 電腦網路 把分佈在不同地理區域的電腦與專門的外部設備用通信線路互連成一個規模大,功能強的網路系統, 從而使眾多的電腦可以方便地互相傳遞信息,共用硬體,軟體,數據信息等資源。 ## ...


網路編程

一、概述

網路編程是指編寫運行在多個設備(電腦)的程式,這些設備都通過網路連接起來。

電腦網路

把分佈在不同地理區域的電腦與專門的外部設備用通信線路互連成一個規模大,功能強的網路系統, 從而使眾多的電腦可以方便地互相傳遞信息,共用硬體,軟體,數據信息等資源。

網路編程目的

  • 直接或間接地通過網路協議與其他電腦實現數據交換,

  • 進行通訊。

網路編程中主要問題

  1. 如何準確的定位網路上的一臺或多台主機,定位主機上的特定的應用?
  2. 找到主機後如何可靠高效地進行數據傳輸?

二、網路通信要素

  • ip + 埠號
  • 通信協議

IP

  • '網際協議'

  • 是 TCP/IP 協議族中最重要的協議之一,也是最重要的互聯網協議之一。這裡的 IP 指 IPV4

  • IP 地址分為五類,主要是前三類

    • A類:0~127
    • B類:128~191
    • C類:192~223
  • ip 地址由 4個十進位數組成,以點隔開

例如:

192.168.10.102

埠號

  • 識別電腦上的進程。因為一臺電腦上有很多的軟體,不同的軟體都有不同的進程號。即識別電腦上的軟體

  • 範圍:0~65535

  • 常用埠號:

    • 下述為服務端埠號,範圍:0~1023

    • HTTP DNS HTTPS FTP
      80 53 443 21
  • 客戶端埠號:49152~65535

埠號與IP地址的組合,得出一個網路套接字:Socket,所以說一些網路編程也被稱為Socket編程

通信協議

說協議前需要瞭解網路體繫結構。

網路體繫結構

以前是OSI參考模型,但由於模型過於理想化,未能在網際網路上進行廣泛推廣。現在國際上的標準是 TCP/IP 參考模型。

網路體繫結構:

而網路通信主要在 傳輸層。所以需要瞭解的通信協議也就是:TCP 與 UDP


TCP

  • 每一條 TCP 連接都會有兩個埠
  • TCP是面向連接的。因為在進行 TCP 通信前需要進行 ”三次握手“ 與。通信結束後需要進行 ”四次揮手“
  • TCP協議進行通信的兩個應用進程:客戶端,服務端。
  • 在連接中可進行大數據量的傳輸 傳輸完畢,需要釋放已建立的連接,效率低 舉例:打電話

UDP

  • 每一條 UDP 連接都會有兩個埠
  • 面向無連接的。進行 UDP通信時,源端不需要確認你是否線上,它只管發送。
  • 將數據,源,目的封裝成數據包,不需要建立連接 每個數據報的大小限制在64K內 發送方不管對方是否準備好,接收方收到也不確認,故是不可靠的
  • 例如:發簡訊。

三、TCP網路編程

1、通過上述可知,網路編程也可為 socket 編程;而 socket 是套接字。即將 埠號拼接到 ip 地址構成的。

2、套接字使用TCP提供了兩台電腦之間的通信機制。 客戶端程式創建一個套接字,並嘗試連接伺服器的套接字。當連接建立時,伺服器會創建一個 Socket 對象。客戶端和伺服器現在可以通過對 Socket 對象的寫入和讀取來進行通信。java.net.Socket 類代表一個套接字,並且 java.net.ServerSocket 類為伺服器程式提供了一種來監聽客戶端,並與他們建立連接的機制。

3、通過如下步驟即可在兩台電腦之間使用套接字建立 TCP 連接:

  • 伺服器實例化一個 ServerSocket 對象,表示通過伺服器上的埠通信。
  • 伺服器調用 ServerSocket 類的 accept() 方法,該方法將一直等待,直到客戶端連接到伺服器上給定的埠。
  • 伺服器正在等待時,一個客戶端實例化一個 Socket 對象,指定伺服器名稱和埠號來請求連接。
  • Socket 類的構造函數試圖將客戶端連接到指定的伺服器和埠號。如果通信被建立,則在客戶端創建一個 Socket 對象能夠與伺服器進行通信。
  • 在伺服器端,accept() 方法返回伺服器上一個新的 socket 引用,該 socket 連接到客戶端的 socket。

當連接建立後,即可通過 I/O 流進行通信。

  • 每一個socket都有一個輸出流和一個輸入流
  • 客戶端的輸出流連接到伺服器端的輸入流,而客戶端的輸入流連接到伺服器端的輸出流。

在 java 中提供了一個類用於獲取一個埠,並且偵聽客戶端請求。如下


ServerSocket 類

伺服器應用程式通過使用 java.net.ServerSocket 類以獲取一個埠,並且偵聽客戶端請求。

構造方法如下:

public ServerSocket()	//創建非綁定伺服器套接字
public ServerSocket(int port)	//創建綁定到特定埠的伺服器套接字。

public ServerSocket(int port, int backlog)	//利用指定的 backlog 創建伺服器套接字並將其綁定到指定的本地埠號。

public ServerSocket(int port, int backlog, InetAddress bindAddr)	//使用指定的埠、偵聽 backlog 和要綁定到的本地 IP 地址創建伺服器。

常用方法:

public int getLocalPort()	//返回此套接字在其上偵聽的埠。
public Socket accept() 		//偵聽並接受到此套接字的連接。
public void setSoTimeout(int timeout)		//通過指定超時值啟用/禁用 SO_TIMEOUT,以毫秒為單位
public void bind(SocketAddress host, int backlog)		//將 ServerSocket 綁定到特定地址(IP 地址和埠號)。

Socket 類

java.net.Socket 類代表客戶端和伺服器都用來互相溝通的套接字。客戶端要獲取一個 Socket 對象通過實例化 ,

而 伺服器獲得一個 Socket 對象則通過 accept() 方法的返回值。

構造方法:

public Socket(String host, int port)		//創建一個流套接字並將其連接到指定主機上的指定埠號。
public Socket(InetAddress host, int port)	//創建一個流套接字並將其連接到指定 IP 地址的指定埠號
public Socket(String host, int port, InetAddress localAddress, int localPort)	//創建一個套接字並將其連接到指定遠程主機上的指定遠程埠。
public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) //創建一個套接字並將其連接到指定遠程地址上的指定遠程埠
public Socket()		//通過系統預設類型的 SocketImpl 創建未連接套接字

常用方法:

public void connect(SocketAddress host, int timeout) 	//將此套接字連接到伺服器,並指定一個超時值。
public InetAddress getInetAddress()						//返回套接字連接的地址。
public int getPort()								//返回此套接字連接到的遠程埠。
public int getLocalPort()							//返回此套接字綁定到的本地埠。
public SocketAddress getRemoteSocketAddress()	//返回此套接字連接的端點的地址,如果未連接則返回 null。
public InputStream getInputStream() 		//返回此套接字的輸入流。
public OutputStream getOutputStream() 		//返回此套接字的輸出流。
public void close() 			//關閉此套接字。

註意:客戶端和伺服器端都有一個 Socket 對象,所以無論客戶端還是服務端都能夠調用這些方法。


InetAddress 類

這個類表示互聯網協議(IP)地址。類中是沒有構造方法的,所以不能 new 。而可以通過如下方法來進行獲取 ip 地址

static InetAddress getByAddress(byte[] addr)		//在給定原始 IP 地址的情況下,返回 InetAddress 對象。
static InetAddress getByAddress(String host, byte[] addr)		//根據提供的主機名和 IP 地址創建 InetAddress。
static InetAddress getByName(String host)		//在給定主機名的情況下確定主機的 IP 地址。
String getHostAddress() 		//返回 IP 地址字元串(以文本表現形式)。
String getHostName() 		//獲取此 IP 地址的主機名。
static InetAddress getLocalHost()		//返回本地主機。
String toString()		//將此 IP 地址轉換為 String。

案例一:TCP 通信

服務端:

public class TcpServer {
    public static void main(String[] args) {
        ByteArrayOutputStream bos = null;
        InputStream is = null;
        Socket socket = null;
        ServerSocket serverSocket = null;
        try {
            //1、設置服務端的地址與埠
            serverSocket = new ServerSocket(9923);

            //2、監聽該埠的請求
            socket = serverSocket.accept();
            //3、讀取信息,通過管道流
            //獲取輸入流
            is = socket.getInputStream();
            //獲取位元組緩衝數組流,用於輸出
            bos = new ByteArrayOutputStream();
            //設置緩衝數組
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1){
                bos.write(buffer, 0, len);
            }
            System.out.println(bos.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //4、資源關閉
            if (null != bos) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != socket) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != serverSocket) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

客戶端:

public class TcpClient {
    public static void main(String[] args) {
        OutputStream outputStream = null;
        Socket socket = null;
        try {
            //1、設置ip地址
            InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
            //2、設置埠
            int port = 9923;
            //3、創建交流的套子介面
            socket = new Socket(inetAddress, port);
            //4、進行交流
            outputStream = socket.getOutputStream();
            outputStream.write("你好,java網路編程".getBytes());

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //5、進行資源關閉
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != socket) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

案例二:TCP 文件

服務端:

public class TcpFileServer {
    public static void main(String[] args) throws Exception {
        //1、設置埠
        ServerSocket serverSocket = new ServerSocket(9923);
        //2、監聽埠
        Socket socket = serverSocket.accept();
        //3、獲取客戶端發送的數據
        InputStream inputStream = socket.getInputStream();
        //將數據寫入該路徑下的文件
        //FileOutputStream fileOutputStream = new FileOutputStream(new File("reseve.txt"));
        FileOutputStream fileOutputStream = new FileOutputStream(new File("/opt/software/reseve.txt"));//虛擬機地址
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1){
            fileOutputStream.write(buffer, 0, len);
        }

        //4、通知客戶端傳輸完畢
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("已接收完畢".getBytes());

        //5、關閉資源
        outputStream.close();
        fileOutputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

客戶端:

public class TcpFileClient {
    public static void main(String[] args) throws Exception {
        //1、獲取埠與地址進行交互
        Socket socket = new Socket("192.168.10.102", 9923);
        //Socket socket = new Socket("127.0.0.1", 9923);
        //2、獲取輸出流,進行輸出文件
        OutputStream outputStream = socket.getOutputStream();
        //3、讀取文件
        FileInputStream fileInputStream = new FileInputStream(new File("20230702_18474242.png"));

        //4、進行上傳
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fileInputStream.read(buffer)) != -1){
            outputStream.write(buffer, 0, len);
        }

        //5、進行斷開連接判斷
        //通知伺服器,已發送完畢
        socket.shutdownOutput();;//已發送完
        //獲取輸入流,獲取服務端發送的數據
        InputStream inputStream = socket.getInputStream();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] bytes = new byte[1024];
        int len2;
        while ((len2 = inputStream.read(bytes)) != -1){
            bos.write(bytes, 0, len2);
        }
        System.out.println(bos.toString());

        //6、關閉資源
        bos.close();
        inputStream.close();
        fileInputStream.close();
        outputStream.close();
        socket.close();
    }
}

註意:tcp 網路編程時,需要先運行服務端,在運行客戶端


四、UDP網路編程

  • 在 UDP 網路編程中,數據是以包發送的,所以需要將數據,目的主機,目的埠封裝在數據包中進行發送。

  • DatagramSocketDatagramPacket 兩個類實現了基於UDP協議的網路程式。

  • UDP 數據報通過數據報套接字 DatagramSocket 發送和接收,系統不保證UDP數據報一定能夠安全送到目的地,也不確定什麼時候可以抵達。

  • DatagramPacket 對象封裝了 UDP 數據報,在數據報中包含了發送端的IP地址和埠號以及接收端的IP地址和埠號。

  • UDP 協議中每個數據報都給出了完整的地址信息,因此無需建立發送方和接收方的連接。如同發快 遞包裹一樣。

案例一:UDP 通信

發送端:

public class UdpSend {
    public static void main(String[] args) throws Exception {
        //1、創建通信鏈接通道
        DatagramSocket datagramSocket = new DatagramSocket();

        //2、創建包
        String msg = "你好";
        InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
        int post = 9923;
        DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, inetAddress, post);


        //3、發送包
        datagramSocket.send(datagramPacket);

        //4、關閉資源
        datagramSocket.close();
    }
}

接收端:

public class UdpReceive {
    public static void main(String[] args) throws IOException {
        //1、創建通信鏈接通道
        DatagramSocket datagramSocket = new DatagramSocket(9923);

        //2、創建接收數據的包
        byte[] buffer = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);

        //3、接收
        datagramSocket.receive(datagramPacket);

        System.out.println(new String(datagramPacket.getData()));//獲取數據
        System.out.println(datagramPacket.getPort());//獲取發射器埠
        System.out.println(datagramPacket.getSocketAddress());//獲取包中的地址 加 發送器的埠
        System.out.println(datagramPacket.getAddress());//獲取包中的地址

        //4、關閉資源
        datagramSocket.close();
    }
}

案例二:UDP 線上聊天

發送端:

public class UdpSend {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket();

        //準備數據
        BufferedReader dataPacket = new BufferedReader(new InputStreamReader(System.in));
        while (true){
            String data = dataPacket.readLine();
            byte[] dataBytes = data.getBytes();
            DatagramPacket packet = new DatagramPacket(dataBytes, 0, dataBytes.length, new InetSocketAddress("192.168.10.102", 9923));
            //發送數據
            socket.send(packet);
            if (data.equalsIgnoreCase("bye")){
                break;
            }
        }

        //關閉資源
        socket.close();

    }
}

接收端:

public class UdpReceive {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(9923);

        //接收多次
       while (true){
           //準備容器接收數據
           byte[] container = new byte[1024];
           DatagramPacket packet = new DatagramPacket(container, 0, container.length);

           //阻塞接收數據
           socket.receive(packet);

           //斷開連接
           byte[] data = packet.getData();
           String receiveData = new String(data);
           System.out.println(receiveData);
           if (receiveData.equalsIgnoreCase("bye")){
               break;
           }
       }
        //關閉資源
        socket.close();
    }
}

案例三:案例二改進為多線程

發送端也是接收端。通過多線程來實現。

發送端:

public class TalkServiceSend implements Runnable{
    private DatagramSocket socket = null;
    private BufferedReader dataPacket = null;
    /**
     * 接收者的ip
     */
    private String receiveIp;
    /**
     * 接收者埠
     */
    private int receivePort;

    public TalkServiceSend(String receiveIp, int receivePort) {
        this.receiveIp = receiveIp;
        this.receivePort = receivePort;
        try {
            socket = new DatagramSocket();
            dataPacket = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true){
            try {
                String data = dataPacket.readLine();
                byte[] dataBytes = data.getBytes();
                DatagramPacket packet = new DatagramPacket(dataBytes, 0, dataBytes.length, new InetSocketAddress(this.receiveIp, this.receivePort));
                //發送數據
                socket.send(packet);
                if (data.equalsIgnoreCase("bye")){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //關閉資源
        socket.close();
    }
}

接收端:

public class TalkServiceReceive implements Runnable{
    DatagramSocket socket = null;
    /**
     * 埠
     */
    private int port;
    /**
     * 發送者
     */
    private String sender;

    public TalkServiceReceive(int port, String sender) {
        this.port = port;
        this.sender = sender;
        try {
            socket = new DatagramSocket(this.port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        //接收多次
        while (true){
            try {
                //準備容器接收數據
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container, 0, container.length);

                //阻塞接收數據
                socket.receive(packet);

                //斷開連接
                byte[] data = packet.getData();
                String receiveData = new String(data);
                System.out.println(sender + " : " + receiveData);
                if (receiveData.equalsIgnoreCase("bye")){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //關閉資源
        socket.close();
    }
}

測試:

public class TalkStudent {
    public static void main(String[] args) {
        //new Thread(new TalkServiceSend("127.0.0.1", 9923)).start();
        new Thread(new TalkServiceSend("10.82.148.136", 9923)).start();//虛擬機地址
        new Thread(new TalkServiceReceive(9924, "老師")).start();
    }
}
public class TalkTeacher {
    public static void main(String[] args) {
        new Thread(new TalkServiceSend("192.168.10.102", 9924)).start();
        new Thread(new TalkServiceReceive(9923, "學生")).start();
    }
}

五、URL編程

  • URL (Uniform Resource Locator): 統一資源定位符,它表示 internet 上某一資源的地址。
  • 它是一種具體的URI,即URL可以用來標識一個資源,而且還指明瞭如何locate:定位這個資源。
  • 通過URL 我們可以訪問Internet上的各種網路資源
  • URL 的 基本結構由 5部分組成: 傳輸協議://主機名:埠號/文件名 #片段名?參數列表
  • 例如:http://localhost:8080/helloworld/index.jsp#a?username=kuangshen&password=123

舉例:

public class UrlTest {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("https://www.jd.com/?cu=true&utm_source=www.baidu.com&utm_medium=tuiguang&utm_campaign=t_1003608409_");
        System.out.println(url.getProtocol()); //獲取URL的協議名
        System.out.println(url.getHost());	//獲取URL的主機名
        System.out.println(url.getPort());	//獲取URL的埠號
        System.out.println(url.getPath());	//獲取URL的文件路徑
        System.out.println(url.getFile());	//獲取URL的文件名
        System.out.println(url.getQuery());	//獲取URL的查詢名
    }
}

案例一:下載文件

public class UrlTest {
    public static void main(String[] args) throws Exception {
        //1、定位到伺服器上的資源位置
        URL url = new URL("https://lmg.jj20.com/up/allimg/4k/s/02/2109250006343S5-0-lp.jpg");
        //2、創建連接
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        
        //對於程式而言,寫出去----》output/writer;讀取---》input/reader
        
        //3、獲取輸入流
        InputStream stream = connection.getInputStream();
        //4、寫入文件
        FileOutputStream outputStream = new FileOutputStream("山水.jpg");
        byte[] bytes = new byte[1024];
        int len;
        while ((len = stream.read(bytes)) != -1){
            outputStream.write(bytes, 0, len);
        }

        //5、關閉資源
        outputStream.close();
        stream.close();
        connection.disconnect();//斷開連接
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • > Vue2.x使用EventBus進行組件通信,而Vue3.x推薦使用`mitt.js`。 > > > 比起Vue實例上的`EventBus`,`mitt.js`好在哪裡呢?首先它足夠小,僅有200bytes,其次支持全部事件的監聽和批量移除,它還不依賴Vue實例,所以可以跨框架使用,React或 ...
  • ![](https://img2023.cnblogs.com/blog/3076680/202308/3076680-20230817155723872-372310672.png) # 1. 基本信息 發佈!設計與部署穩定的分散式系統 第2版 Release It! Design and Dep ...
  • > 任何傻瓜都可以寫出電腦能懂的代碼,但好的程式員可以寫出人類能懂的代碼—–Martin Fowler 如果你是新手,你可能會問,為什麼代碼需要設計原則? 我想說的是肯定不是為了故作高深,存在即是合理。 如果寫了一個簡單的程式,你可能不需要設計原則。 如果你寫了一個複雜的,但是之後再也不會改,那麼 ...
  • 領域區域設計的分層架構模型其實是在不斷優化和發展的,從最早的傳統直腸子式的四層架構模型,逐漸演變成目前以依賴倒置為原則的新的四層架構模型,從而實現了各層對基礎設施層的解耦。 DDD中的分層架構很好的應用了[關註點分離原則](http://www.cnblogs.com/LittleFeiHu/p/6 ...
  • 本文通過docker快速部署elasticsearch8版本,再添加一臺組成集群,並且部署kibana用於常規查詢操作,以及一些常見的es操作 ...
  • 本文旨在根據LOVE2D官方文檔和教程實現打磚塊的游戲,記錄部分實現過程和重要知識點 - 目標摧毀所有磚塊 - 玩家控制球拍左右滑動反彈小球 - 小球摧毀磚塊 - 小球保持在屏幕內 - 小球碰到屏幕底部,GAME OVER ## 引擎配置 ```lua -- conf.lua love.conf = ...
  • ## 前提 之前曾經寫過一篇[《SpringBoot3.x 原生鏡像-Native Image 嘗鮮》](https://vlts.cn/post/spring-boot-native-image-demo),當時`SpringBoot`處於`3.0.0-M5`版本,功能尚未穩定。這次會基於`Spr ...
  • ### POM.XML配置 ``` 4.0.0 com.shouke des-utils 1.0 1.8 ${java.version} ${java.version} UTF-8 UTF-8 cn.hutool hutool-all 4.1.0 ``` ## 代碼實現 ```groovy pack ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...