java基礎-網路編程

来源:https://www.cnblogs.com/lyh1024/archive/2022/10/14/16792400.html
-Advertisement-
Play Games

以下為本人的學習筆記 1.網路編程基本概念 1.1 什麼是電腦網路 把發佈在不同地理區域的電腦與專門的外部設備用通信線路互連成一個規模大、功能強的網路系統,從而使眾多的電腦可以方便地互相傳遞消息,共用硬體、軟體、數據消息等資源 1.2 電腦網路的主要功能 資源共用 信息傳輸與集中處理 均衡負 ...


以下為本人的學習筆記

 

1.網路編程基本概念

1.1 什麼是電腦網路

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

 

1.2 電腦網路的主要功能
  • 資源共用

  • 信息傳輸與集中處理

  • 均衡負荷與分佈處理

  • 綜合信息服務(www/綜合業務數字網路ISDN等)

 

1.3網路通信協議

要使電腦連成的網路能夠互通信息,需要對數據傳輸速率、傳輸代碼、代碼結構、傳輸控制步驟、出錯控制等制定一組標準,這一組共同遵守的通信標準就是網路通信協議,不同的電腦之間必須使用相同的通訊協議才能進行通信

網路通信介面

為了使兩個節點之間能夠進行對話,必須在他們之間建立通信工具(即介面),使彼此之間能進行信息交換。介面包括兩部分:

1)硬體裝置:實現節點之間的信息傳送(網線....)

2)軟體裝置:規定雙方進行的約定協議

 

1.4 TCP/IP

TCP/IP;參數控制協議/網際網路協議,又叫網路通訊協議,這個協議是Internet最基本的協議、Internet國際互聯網路的基礎,簡單來說,就是由網路層的IP協議和傳輸層的TCP協議組成的。

IP地址:網路中每台電腦的一個標識號,本地IP:127.0.0.1 或者 localhost

埠號(PORT):埠號的範圍:0-65535之間,0-1023之間的埠數是用於一些知名的網路服務和應用,通過埠號找到具體要通信的軟體

 

1.5程式開髮結構

網路編程主要是指完成C/S程式的開發,程式的開髮結構有兩種:

  • C/S(客戶端/伺服器)

開發兩套程式,兩套程式需要同時維護,例如:QQ。CS程式一般比較穩定

  • B/S(瀏覽器/伺服器)

開發一套程式,客戶端使用瀏覽器進行訪問,例如:各個論壇。BS程式一般穩定性較差,而且安全性較差。

但是,C/S的程式開發在實際的java應用中很少,而且整個java基本上都是以B/S為主

C/S程式主要可以完成以下兩種程式的開發:

  • TCP:(Transmission Control Protocol) 傳輸控制協議,採用三方握手的方式,保證準確的連接操作

  • UDP:(User Datagram Protocol) 數據報協議,發送數據報,例如:手機簡訊或者是QQ消息

TCP、UDP的數據幀格式簡單圖例:

其中協議類型用於區分TCP、UDP

 

2.網路編程TCP協議

2.1TCP程式概述

TCP是一個可靠的協議,面向連接的協議

實現TCP程式,需要編寫伺服器端和客戶端,Java API為我們提供了java.net包,為實現網路應用程式提供類

ServerSocket:此類實現伺服器套接字

Socket:此類實現客戶端套接字(也可以就叫“套接字”)

硬體都有驅動,網路驅動層指的是網卡的驅動

通過Socket來實現網路編程,Socket是網路驅動層提供給應用程式編程的介面和一種訪問機制,

解釋:數據寫到Socket中,Socket就會把數據對接到驅動層,驅動層把數據對接到網卡,再通過網線傳出去

也可以將Socket想象成一個快遞員

 

2.2 數據發送過程

 

2.3 數據接收過程

 

2.4 實現伺服器端與客戶端程式

伺服器端:

public class ServerSocket extends Object implements Closeable

這個類實現了伺服器套接字。 伺服器套接字等待通過網路進入的請求。 它根據該請求執行一些操作,然後可能將結果返回給請求者。

method 說明
ServerSocket(int port) 創建綁定到指定埠的伺服器套接字。
setSoTimeout(int timeout) 啟用/禁用 SO_TIMEOUT帶有指定超時,以毫秒為單位。
getInetAddress() 返回此伺服器套接字的本地地址。
accept() 偵聽要連接到此套接字(socket)並接收它。

客戶端:

public class Socket extends Object implements Closeable

該類實現客戶端套接字(也稱為“套接字”)。 套接字是兩台機器之間通訊的端點。

method 說明
Socket(InetAddress address, int port) 創建流套接字並將其連接到指定IP地址的指定埠號
getInputStream() 返回此套接字的輸入流。
getOutputStream() 返回此套接字的輸出流。
setSoTimeout(int timeout) 啟用/禁用指定超時的 SO_TIMEOUT(以毫秒為單位)。

 

3.TCP實現ECHO程式

Echo,意為應答,程式的功能是客戶端向伺服器發送一個字元串,伺服器不做任何處理,直接把字元串返回給客戶端,Echo程式是最為基本的客戶/伺服器程式。(相當於java的HelloWorld)

public class EchoServerDeom{
    public static void main(String[] args){
    
        //1.創建一個伺服器端的Socket(1024-65535的埠號)
            try{
                ServerSocket server = new ServerSocket(port:6666)
                System.out.println("伺服器已啟動,正在等待客戶端的連接...");
                //2.等待客戶端的連接,造成阻塞,如果有客戶端連接成功,立即返回一個Socket對象
                Socket socket = server.accpet();   
                System.out.println("客戶端連接成功:"+server.getInetAddress().getHostAddress());
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream());
                 //通過輸入流讀取網路數據,如果沒有數據,那麼會阻塞
                 String info = br.readLine();
                 System.out.println(info);   
                 //獲取輸出流,向客戶端返回消息
                 PrintStream ps = new PrintStream (new BufferedOutputStream(socket.getOutputStream()));
                  ps.println("echo"+info);
                  ps.flush();
                  //關閉
                  ps.close();
                  br.close();                                     
                                                       
             }catch (IOException e){
                 e.printStackTrace();
            }
    }
}
​
public class EchoClientDeom{
    public static void main(String[] args){
        //1.創建一個Socket對象,指定要連接的伺服器
        try{
            Socket socket = new Socket("localhost",6666);//主機名+埠號
            //獲取socket的輸入輸出流
            PrintStream ps = new PrintStream(new BufferedOutputStream(socket.getOutPutStream()));
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            
            ps.println("hello,my name is bin");
            ps.flush();
            //讀取伺服器端返回的數據
            String info = br.readLine();
            System.out.println(info);
            ps.close();
            br.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }
}

兩個對象創建成功後面就是流的操作

 

4.伺服器與多客戶端通信

要想伺服器同時支持多個客戶端的連接,就必須加入多線程的處理機制,將每一個連接的客戶端都創建一個新的線程對象(用迴圈)

伺服器端通過加入線程池來處理多個客戶端請求,簡單的設置線程數可以與CPU核數匹配,過多的線程數空閑會消耗伺服器為資源

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//伺服器,用迴圈處理多個客戶端
public class ServerSocketDemo2 {
    public static void main(String[] args) {
        try {
            ServerSocket server = new ServerSocket(6666);
            System.out.println("伺服器已啟動,等待客戶端連接...");
            ExecutorService es = Executors.newFixedThreadPool(3);
            
            while (true){
                Socket socket = server.accept();
                System.out.println(socket.getInetAddress().getHostAddress());
                es.execute(new UserThread(socket));//一個線程處理一個客戶端,將一個客戶端socket作為線程的一個參數
            }
​
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
//用來處理客戶端請求的線程
class UserThread implements Runnable{
    private Socket socket;
    UserThread(Socket socket){
        this.socket = socket;
    }
    public  void run(){
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
​
            String info = br.readLine();
            System.out.println(info);
​
            pw.println("echo:"+info);
            pw.flush();
            br.close();
            pw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
//客戶端
public class MutilClientDemo {
    public static void main(String[] args) {
        try {
            Scanner input = new Scanner(System.in);
            //創建一個socket對象,指定要連接的伺服器
            Socket socket = new Socket("localhost", 6666);
​
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintStream ps = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
​
            System.out.println("請輸入一段話:");
            String info = input.nextLine();
            ps.println(info);
            ps.flush();
​
            //讀取伺服器返回的數據
            info = br.readLine();
            System.out.println(info);
​
            br.close();
            ps.close();
​
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

5.多客戶端之間的通信

伺服器可以與多個客戶端實現通信了,那我們真正的目的就是要實現多個客戶端之間的通信,使用TCP協議實現的方案是:客戶端的數據包通過伺服器中轉,發送到另一個客戶端,如下圖所示:

多客戶端間通信案例:

伺服器通過消息類型來判斷發送消息的客戶端是什麼意圖,消息類型是我們自定義的標記

圖解分析:

伺服器端:

/*伺服器作為一個中轉,轉發消息給多個客戶端之間*/
public class Server {
    public static void main(String[] args) {
        //2.創建集合,保存客戶端處理的線程,用來找其他指定線程
        Vector<UserThread> vector = new Vector<UserThread>();
        //3.創建線程池
        ExecutorService es = Executors.newFixedThreadPool(5);
        //1.創建伺服器端的Socket
        try {
            ServerSocket server = new ServerSocket(7777);
            System.out.println("伺服器已啟動,正在等待連接...");
            while (true){
                //4.接收一個客戶端的socket
                Socket socket = server.accept();
                UserThread user = new UserThread(socket,vector);
                //5.線程執行一個客戶端
                es.execute(user);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
//客戶端處理的線程
class UserThread implements Runnable{
    private String name ;//客戶端的用戶名稱(唯一)
    private Socket socket;
    private Vector<UserThread> vector;//客戶端處理線程的集合
    private ObjectInputStream ois;
    private ObjectOutputStream oos;
    private boolean flag = true;
​
    public UserThread(Socket socket, Vector<UserThread> vector) {
        this.socket = socket;
        this.vector = vector;
        vector.add(this);
    }
    @Override
    public void run() {
        try {
            //6.輸出客戶端socket主機地址
            System.out.println("客戶端"+socket.getInetAddress().getHostAddress());
            //7.構建序列化輸入輸出對象流,
            oos = new ObjectOutputStream(socket.getOutputStream());
            ois = new ObjectInputStream(socket.getInputStream());
​
            while (flag){
                //8.讀取消息對象
                Message msg = (Message)ois.readObject();
                //9.判斷消息類型
                int type = msg.getType();
                switch (type){
                    //發送消息的類型
                    case MessageType.TYPE_SEND:
                        String to = msg.getTo();
                        UserThread ut ;
                        int size = vector.size();
                        //遍歷線程集合里的線程名字,符合就把消息writ給該線程
                        for (int i = 0; i < size; i++) {
                            ut = vector.get(i);//取一個變數裝這個線程
                            if (to.equals(ut.name) && ut != this){
                                ut.oos.writeObject(msg);//把該消息發給該線程
                                break;
                            }
                        }
​
                        break;
                    //登錄消息類型
                    case MessageType.TYPE_LOGIN:
                        //獲取發送者名字
                        name = msg.getFrom();
                        msg.setInfo("歡迎你:");
                        //輸出客戶端歡迎數據
                        oos.writeObject(msg);
                        break;
                }
            }
            //10.關閉流
            ois.close();
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

客戶端:

public class Client {
    public static void main(String[] args) {
​
        Scanner input = new Scanner(System.in);
        ExecutorService es = Executors.newSingleThreadExecutor();
        try {
            //1.創建一個客戶端的socket
            Socket socket = new Socket("localhost",7777);
            System.out.println("伺服器連接成功...");
            //2.構建序列化輸入輸出對象流
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            //3.向伺服器發送登錄消息
            System.out.println("請輸入名稱:");
            String name = input.nextLine();
            Message msg = new Message(name,null,MessageType.TYPE_LOGIN,null);
            oos.writeObject(msg);
            msg = (Message)ois.readObject();
            System.out.println(msg.getInfo()+msg.getFrom());
            
            //啟動(不斷)讀取消息的線程
            es.execute(new ReadInfoThread(ois));
​
            //使用主線程來實現發送消息
            boolean flag = true;
            while(flag){
                msg = new Message();
                System.out.println("To:");
                msg.setTo(input.nextLine());
                msg.setFrom(name);
                msg.setType(MessageType.TYPE_SEND);
                System.out.println("Info:");
                msg.setInfo(input.nextLine());
                oos.writeObject(msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
//讀取消息
class ReadInfoThread implements Runnable{
​
    private ObjectInputStream in;
    private  boolean flag = true;
​
    public ReadInfoThread(ObjectInputStream in) {
        this.in = in;
    }
    public void setFlag(boolean flag){
        this.flag= flag;
    }
    @Override
    public void run() {
        try {
        //不斷地讀取消息
        while (flag){
​
                Message  message = (Message)in.readObject();
                System.out.println("["+message.getFrom()+"]對我說:"+message.getInfo());
        }
        if (in!=null){
            in.close();
        }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

 

import java.io.Serializable;
​
/*消息包*/
public class Message implements Serializable {//序列化對象實現Serializable介面
​
    private String from;//發送者
    private String to;//接收者
    private int type;//消息類型
    private String info;//消息
​
    public Message() {
    }
    public Message(String from, String to, int type, String info) {
        this.from = from;
        this.to = to;
        this.type = type;
        this.info = info;
    }
    public String getFrom() {
        return from;
    }
    public void setFrom(String from) {
        this.from = from;
    }
    public String getTo() {
        return to;
    }
    public void setTo(String to) {
        this.to = to;
    }
    public int getType() {
        return type;
    }
    public void setType(int type) {
        this.type = type;
    }
    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
    @Override
    public String toString() {
        return "Message{" +
                "from='" + from + '\'' +
                ", to='" + to + '\'' +
                ", type=" + type +
                ", info='" + info + '\'' +
                '}';
    }
}

 

public final class MessageType {
​
    public static final int TYPE_LOGIN = 0x1;//登錄消息類型
    public static final int TYPE_SEND = 0x2;//發送消息的類型
}

 

6.網路編程UDP協議

1.UDP協議概述

UCP是User Datagram Protocol的簡稱,是一種無連接的協議,每個數據報都是一個獨立的信息,包括完整的源地址或目的地址,它在網路上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的,每個被傳輸的數據報必須限定在64KB之內。

主要使用以下兩個類:

DatagramPacket:此類表示數據報包

DatagramSocket:此類表示用來發送和接收數據報包的套接字

UDP是無連接的,減少了開銷和發送數據之前的延遲,不保證可靠,UDP的報頭長度要小於TCP的包頭長度,例如QQ文件傳輸,pplive等都是使用UDP協議

伺服器端:

public class UDPServerDeom{
    public static void main(String[] args){
    
        String info = "good good 天天";
        byte[] bytes = info.getBytes();
        try{
        DatagramPacket dp = new DatagramPacket(bytes,/**數據報包數據*/
                                               0,/**0表示第0個位置,分組數據偏移量*/
                                               bytes.length,/**數組長度*/
                                               InetAddress.getByName("127.0.0.1"),/**目的地址*/
                                              8000/**目的埠號*/);
            //本程式的埠號
            DatagramSocket socket = new DatagramSocket(9000);
            socket.send(dp);   
        } catch(UnknownHostException e){
            e.printStackTrace();
        } catch( IOException e){
            e.printStackTrace();
        }
    }
}

客戶端:客戶端要先啟動,在receive()阻塞,等待server發數據報

public class UDPClientDeom{
    public static void main(String[] args){
    
    byte[] bytes = new byte[1024];
    //封裝成數據報包
    DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
    try{
        DatagramSocket socket = new DatagramSocket(8000);
        System.out.println("正在接收數據中...");
        socket.receive(dp);//接收數據,會造成阻塞
        String s = new String(dp.getData(),0,dp.getLength());//從data中取,從0 到dp.getLength()
        System.out.println(s);
        socket.close();
        } catch(UnknownHostException e){
            e.printStackTrace();
        } catch( IOException e){
            e.printStackTrace();
        }
    }
}

 

7.URL

URL概述

URL(uniform resource location)類URL代表一個統一資源定位符,是互聯網上標準資源的地址,它是指向互聯網“資源”的指針,互聯網的每個文件都有唯一的一個URL。抽象類URLConnection是所有類的超類,它代表應用程式和URL之間的通信鏈接

public class URLDeom{
    public static void main(String[] args){
    try{
        URL url = new URL("https://pic.cnblogs.com/avatar/2988753/20221012224248.png");//資源路徑
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();//打開鏈接,因為圖片地址是http協議,可以用HttpURLConnection
        BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("D:\\xx\\wukong.jpg"));
        byte[] bytes = new byte[1024];
        int len = -1 ;
        while((len = in.read(bytes))!=-1){
            out.write(bytes,0,len);
                out.flush();
        }
        in.close();
        out.close();
        System.out.println("下載成功... ");
        } catch(MalformedURLException e){
            e.printStackTrace();
        } catch( IOException e){
            e.printStackTrace();
        }
    }
}
​
​

 

8.MINA框架

  • 什麼是MINA?一句話就是:一個簡潔易用的基於TCP/IP通信的java框架

  • 下載地址:http://mina.apache.org/downloads-mina.html 下載zip包

  • 一個簡單的網路程式需要的最少jar包:mina-core-2.0.16.jar、slf4j-api-1.7.21.jar

  • 開發一個MINA應用,簡單的說,就是①創建連接,②設定過濾規則,③編寫自己的消息處理器

  • Mina框架可以幫助我們快速開發高性能、高擴展的網路通信應用,Mian提供了事件驅動、非同步操作的編程模型,預設使用NIO作為底層支持

    示例:
public class Server{
    public static void main(String[] args){
        //創建一個非阻塞的Server端Socket,用NIO
​
        SocketAcceptor acceptor= new NioSocketAcceptor();//創建接收數據的過濾器
​
        DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();//chain鏈
        //設定這個過濾器將一行一行(/r/n)的讀取數據
        chain.addLast("myChin",new ProtocolCodecFilter(new TextLineCodecFactory()));
        //如,設定伺服器端的消息處理器:一個MainaServerHandler對象
        acceptor.setHandler(new MinaServerHandler());
        int bindPort = 9999;//伺服器埠號
        
        try{
            //綁定埠,啟動伺服器
            //立即返回
            acceptor.bind(new InetSocketAddress(bindPort));
        }catch(IOException e){
            e.printStackTrace();
        }
        System.out.println("Mina Server is running: = "+bindPort);
    }
}

 

/**
伺服器端的消息處理器
*/
public class MinaServerHandler  extends IoHandleAdapter{
    //一次會話被打開
    public void sessionOpened(IoSession session) throws Exception{
        super.sessionOpened(session);
        System.out.println("welcome client"+session.getRemoteAddress());
    }
    //會話被關閉
    public void sessionClosed(IoSession session) throws Exception{
        super.sessionClosed(session);
        System.out.println("client closed");
    }
    //接收消息
    public void messageReceived(IoSession session,Object message) throws Exception{
        super.messageReceived(session,message);
        String msg = (String)message;//接收到的消息對象
        System.out.println("收到客戶端發來的消息: "+msg);
        //向客戶端發送消息對象
        session.write("echo:"+msg);
    }
    
    
    }
}

使用telnet測試:telnet localhost 9999

public class Client{
    public static void main(String[] args){
        NioSocketConnector connector = new NioSocketConnector();//創建接收數據的過濾器
        DefaultIoFilterChainBuilder chain = connector.getFilterChain();
        //設定這個過濾器將一行一行(/r/n)的讀取數據
        chain.addLast("myChin",new ProtocolCodecFilter(new TextLineCodecFactory()));
        //如,設定伺服器端的消息處理器:一個SamplMainaServerHandler對象
        connector.setHandler(new MinaServerHandler());
        connector.setConnectTimeoutMillis(30);//Set connect timeout.
        //連接到伺服器:
        ConnectFuture cf = connector.connect(new InsetSocketAddress("localhost",9999));
        //等待連接成功,立即返回
        cf.awaitUninterruptibley();
        Scanner input = new Scanner(System.in);
        while(true){
             System.out.println("請輸入:");
             String info = input.nextLine();
             //發送消息
            cf.getSession().write(info);
        }
        //等待伺服器連接關閉,結束長連接
        //cf.getSession().getCloseFuture().awaitUninterruptibly();//會阻塞
        //connector.dispose();  //釋放    
    }
}

 

public class SampleMinaServerHandler extends IoHandleAdapter{
    //當一個客戶端連接進入時
    public void sessionOpened(IoSession session) throws Exception{
        System.out.println("incomming client"+session.getRemoteAddress());
        super.sessionOpened(session);
​
        session.writ("我來啦");
​
    }
    //當一個客戶端關閉時
    public void sessionClosed(IoSession session) {
                super.sessionClosed(session);
​
       System.out.println("client closed");
    }
    //當一個客戶端發送的消息到達時:
    public void messageReceived(IoSession session,Object message) throws Exception{
        super.messageReceived(session,message);
​
        //我們已設定了伺服器解析消息的規則是一行一行讀取,這裡就可轉為String;
        String msg = (String)message;
        System.out.println("收到伺服器端發來的消息: "+msg);
        //測試將消息會送給客戶端
        session.write(msg);
    }
   } 
    

使用Mina直接傳送對象

1.public class User info implements java.io.Serializable

2.伺服器,客戶端都設定以對象為單位

//設定這個過濾器將以對象為單位讀取數據

ProtocolCodecFilter filter = new ProtocolCodecFilter(new ObjectSerializationCodecFactory());

chain.addLast("objectFilter",filter);

3.接收對象

public void messageReceived(IoSession session,Object message) throws Exception{

//我們已設定了伺服器解析消息的規則一個Userinfo對象為單位傳輸:

Userinfo us = (Userinfo)message;

}

public class Message implements Serializable{
    private String from ;
    private String to; 
    private String type;
    private String info;
    ......
}

 

■免責申明
⒈ 本站是純粹個人學習網站,與朋友交流共賞,不存在任何商業目的。
⒉ 本站利用了部分網路資源,版權歸原作者及網站所有,如果您對本站所載文章及作品版權的歸屬存有異議,請立即通知我們,我們將在第一時間予以刪除,同時向你表示歉意!

 

2022-10-14 17:33:19

 

 

 

 

 

 


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

-Advertisement-
Play Games
更多相關文章
  • 在 《JS 模塊化》系列開篇中,曾提到前端技術的發展不斷融入很多後端思想,形成前端的“四個現代化”:工程化、模塊化、規範化、流程化。在該系列文章中已詳細介紹了模塊化的發展及四種模塊化規範。本文簡單聊聊規範化中的 git 規範。 ...
  • 這段時間在開發一個騰訊文檔全品類通用的 HTML 動態服務,為了方便各品類接入的生成與部署,也順應上雲的趨勢,考慮使用 Docker 的方式來固定服務內容,統一進行製品版本的管理。本篇文章就將我在服務 Docker 化的過程中積累起來的優化經驗分享出來,供大家參考。 以一個例子開頭,大部分剛接觸 D ...
  • 1 什麼是流程引擎 流程引擎是一個底層支撐平臺,是為提供流程處理而開發設計的。流程引擎和流程應用,以及應用程式的關係如下圖所示。 常見的支撐場景有:Workflow、BPM、流程編排等。本次分享,主要從BPM流程引擎切入,介紹流程引擎的架構設計方法。 1.1 什麼是流程 簡單來說,流程就是一系列活動 ...
  • 顧名思義,迭代器就是用於迭代操作的對象,其能夠像有序序列一樣迭代獲取集合中對象,並且能夠記錄下當前所在位置,因此也稱游標。 ...
  • emqx連接啟用jwt令牌認證 jwt令牌 概述 JWT 即 JSON Web Tokens 是一種開放的,用於在兩方之間安全地表示聲明的行業標準的方法(RFC 7519)。 組成 令牌的形式 xxx.yyy.zzz eyJhbGciOiJIUzI1NiJ9 .eyJleHAiOjE2NjU0Nzc ...
  • 原文:JavaFx 使用字體圖標記錄 - Stars-One的雜貨小窩 之前其實也是研究過關於字體圖標的使用,還整了個庫Tornadofx學習筆記(4)——IconTextFx開源庫,整合5000+個字體圖標 - Stars-one - 博客園 由於之前並不是太過於講解字體圖標,最近又是抽空研究了一 ...
  • JDBC和連接池02 3.ResultSet[結果集] 基本介紹 表示資料庫結果集的數據表,通常通過執行查詢資料庫的語句生成 ResultSet對象保持一個游標指向其當前的數據行,最初,游標位於第一行的之前 next方法將游標移動到下一行,並且由於在ResultSet對象中沒有更多行時返回false ...
  • 配置環境變數的目的:使在任意目錄下都能執行java.exe這個應用程式 兩種方法 方法一 1找到jdk安裝的路徑,打開bin目錄(因為java.exe這個程式在bin目錄裡面),複製當前路徑 2右擊此電腦,打開屬性 3打開高級系統設置 4打開環境變數 5打開path,編輯 6 新建,粘貼複製的地址, ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...