二十一章網絡通信

計算機網絡實現了多臺計算機間的互聯,使得它們彼此之間能夠進行數據交流。網絡應用程序就是在已連接的不同計算機上運行的程序,這些程序借助于網絡協議,相互之間可以交換數據。編寫網絡應用程序前,首先必須明確所要使用的網絡協議。TCP/IP協議是網絡應用程序的首選

21.1 網絡程序設計基礎

網絡程序設計編寫的是與其他計算機進行通信的程序。Java已經將網絡程序所需要的元素封裝成不同的類,用戶只要創建這些類的對象,使用相應的方法,即使不具備有關的網絡知識,也可以編寫出高質量的網絡通信程序。

21.1.1 局域網與互聯網

為了實現兩臺計算機的通信,必須用一個網絡線路連接兩臺計算機

服務器是指提供信息的計算機或程序,客戶機是指請求信息的計算機或程序。網絡用于連接服務器與客戶機,實現兩者間的相互通信。但是,有時在某個網絡中很難將服務器與客戶機區分開。我們通常所說的局域網(Local Area Network,LAN),就是一群通過一定形式連接起來的計算機,它可以由兩臺計算機組成,也可以由同一區域內的上千臺計算機組成。將LAN延伸到更大的范圍,這樣的網絡稱為廣域網(Wide Area Network,WAN)。我們熟悉的互聯網(Internet),就是由無數的LAN和WAN組成的。

21.1.2 網絡協議

網絡協議規定了計算機之間連接的物理、機械(網線與網卡的連接規定)、電氣(有效的電平范圍)等特征,計算機之間的相互尋址規則,數據發送沖突的解決方式,長數據如何分段傳送與接收等內容。就像不同的國家有不同的法律一樣,目前網絡協議也有多種。下面簡單地介紹幾個常用的網絡協議。

1.IP協議

IP是Internet Protocol的簡稱,是一種網絡協議。Internet網絡采用的協議是TCP/IP協議,其全稱是Transmission Control Protocol/Internet Protocol。Internet依靠TCP/IP協議,在全球范圍內實現了不同硬件結構、不同操作系統、不同網絡系統間的互聯。在Internet網絡上存在著數以億計的主機,每臺主機都用網絡為其分配的Internet地址代表自己,這個地址就是IP地址。到目前為止,IP地址用4個字節,也就是32位的二進制數來表示,稱為IPv4。為了便于使用,通常取用每個字節的十進制數,并且每個字節之間用圓點隔開來表示IP地址,如192.168.1.1。現在人們正在試驗使用16個字節來表示IP地址,這就是IPv6,但IPv6還沒有投入使用。

TCP/IP模式是一種層次結構,共分為4層,分別為應用層、傳輸層、互聯網層和網絡層。各層實現特定的功能,提供特定的服務和訪問接口,并具有相對的獨立性。

2.TCP與UDP協議

在TCP/IP協議棧中,有兩個高級協議是網絡應用程序編寫者應該了解的,即傳輸控制協議(Transmission Control Protocol,TCP)與用戶數據報協議(User Datagram Protocol,UDP)。

TCP協議是一種以固接連線為基礎的協議,它提供兩臺計算機間可靠的數據傳送。TCP可以保證數據從一端送至連接的另一端時,能夠確實送達,而且抵達的數據的排列順序和送出時的順序相同。因此,TCP協議適合可靠性要求比較高的場合。就像撥打電話,必須先撥號給對方,等兩端確定連接后,相互才能聽到對方說話,也知道對方回應的是什么。

HTTP、FTP和Telnet等都需要使用可靠的通信頻道。例如,HTTP從某個URL讀取數據時,如果收到的數據順序與發送時不相同,可能就會出現一個混亂的HTML文件或是一些無效的信息。

UDP是無連接通信協議,不保證數據的可靠傳輸,但能夠向若干個目標發送數據,或接收來自若干個源的數據。UDP以獨立發送數據包的方式進行。這種方式就像郵遞員送信給收信人,可以寄出很多信給同一個人,且每一封信都是相對獨立的,各封信送達的順序并不重要,收信人接收信件的順序也不能保證與寄出信件的順序相同。

UDP協議適合于一些對數據準確性要求不高,但對傳輸速度和時效性要求非常高的網站,如網絡聊天室、在線影片等。這是由于TCP協議在認證上存在額外耗費,可能使傳輸速度減慢,而UDP協議即使有一小部分數據包遺失或傳送順序有所不同,也不會嚴重危害該項通信。

注意

一些防火墻和路由器會設置成不允許UDP數據包傳輸,因此若遇到UDP連接方面的問題,應先確定所在網絡是否允許UDP協議。

21.1.3 端口與套接字

一般而言,一臺計算機只有單一的連到網絡的物理連接(Physical Connection),所有的數據都通過此連接對內、對外送達特定的計算機,這就是端口。網絡程序設計中的端口(port)并非真實的物理存在,而是一個假想的連接裝置。端口被規定為一個在0~65535的整數。HTTP服務一般使用80端口,FTP服務使用21端口。假如一臺計算機提供了HTTP、FTP等多種服務,那么客戶機會通過不同的端口來確定連接到服務器的哪項服務上,如圖21.3所示。

通常,0~1023的端口數用于一些知名的網絡服務和應用,用戶的普通網絡應用程序應該使用1024以上的端口數,以避免端口號與另一個應用或系統服務所用端口沖突。

網絡程序中的套接字(Socket)用于將應用程序與端口連接起來。套接字是一個假想的連接裝置,就像插座一樣可連接電器與電線,如圖21.4所示。Java將套接字抽象化為類,程序設計者只需創建Socket類對象,即可使用套接字。

?

21.2 TCP程序

TCP網絡程序設計是指利用Socket類編寫通信程序。利用TCP協議進行通信的兩個應用程序是有主次之分的,一個稱為服務器程序,另一個稱為客戶機程序,兩者的功能和編寫方法大不一樣。

①——服務器程序創建一個ServerSocket(服務器端套接字)對象,調用accept()方法等待客戶機來連接。

②——客戶端程序創建一個Socket對象,請求與服務器建立連接。

③——服務器接收客戶機的連接請求,同時創建一個新的Socket對象與客戶建立連接。隨后服務器繼續等待新的請求。

21.2.1 InetAddress類

java.net包中的InetAddress類是與IP地址相關的類,利用該類可以獲取IP地址、主機地址等信息。

?使用InetAddress類的getHostName()和getHostAddress()方法獲得本地主機的本機名、本機IP地址。

package Package21;import java.net.InetAddress;//導入包
import java.net.UnknownHostException;public class Address {//創建類public static void main(String[] args) {//創建InetAddress對象// TODO Auto-generated method stubInetAddress ip;try {//捕捉可能出現的異常ip = InetAddress.getLocalHost();//實例化對象String locaIname = ip.getHostName();//獲取本機名String locaIip = ip.getHostAddress();//獲取本機IP地址System.out.println("本機名:"+locaIname);//將本機名輸出System.out.println("本機IP地址:"+locaIip);//將本機IP地址輸出}catch(UnknownHostException e) {e.printStackTrace();//輸出異常信息}}
}

結果:

注意

InetAddress類的方法會拋出UnknownHostException異常,所以必須進行異常處理。這個異常在主機不存在或網絡連接錯誤時發生。

21.2.2 ServerSocket類

java.net包中的ServerSocket類用于表示服務器套接字,其主要功能是等待來自網絡上的“請求”,它可通過指定的端口來等待連接的套接字。服務器套接字一次可以與一個套接字連接。如果多臺客戶機同時提出連接請求,服務器套接字會將請求連接的客戶機存入列隊中,然后從中取出一個套接字,與服務器新建的套接字連接起來。若請求連接數大于最大容納數,則多出的連接請求被拒絕。隊列的默認大小是50。

ServerSocket類的構造方法通常會拋出IOException異常,具體有以下幾種形式:

  1. ?ServerSocket():創建非綁定服務器套接字。
  2. ServerSocket(int port):創建綁定到特定端口的服務器套接字。
  3. ServerSocket(int port, int backlog):利用指定的backlog創建服務器套接字,并將其綁定到指定的本地端口號上。
  4. ServerSocket(int port, int backlog, InetAddress bindAddress):使用指定的端口、偵聽backlog和要綁定到的本地IP地址創建服務器。這種情況適用于計算機上有多塊網卡和多個IP地址的情況,用戶可以明確規定ServerSocket在哪塊網卡或哪個IP地址上等待客戶的連接請求。

調用ServerSocket類的accept()方法,會返回一個和客戶端Socket對象相連接的Socket對象。服務器端的Socket對象使用getOutputStream()方法獲得的輸出流,將指向客戶端Socket對象使用getInputStream()方法獲得的那個輸入流;同樣,服務器端的Socket對象使用getInputStream()方法獲得的輸入流,將指向客戶端Socket對象使用getOutputStream()方法獲得的那個輸出流。也就是說,當服務器向輸出流寫入信息時,客戶端通過相應的輸入流就能讀取,反之亦然。

注意

accept()方法會阻塞線程的繼續執行,直到接收到客戶的呼叫。如果沒有客戶呼叫服務器,那么System.out.println("連接中")語句將不會執行。語句如果沒有客戶請求,accept()方法沒有發生阻塞,肯定是程序出現了問題。通常是使用了一個被其他程序占用的端口號,ServerSocket綁定沒有成功。

yu = server.accept();

System.out.println("連接中");

21.2.3 TCP網絡程序設計

明白了TCP程序工作的過程,就可以編寫TCP服務器程序了。在網絡編程中,如果只要求客戶機向服務器發送消息,不要求服務器向客戶機發送消息,稱為單向通信。客戶機套接字

和服務器套接字連接成功后,客戶機通過輸出流發送數據,服務器則通過輸入流接收數據。下面是簡單的單向通信的實例。

【例21.2】創建TCP/IP協議服務器

package Package21;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;public class MyServer {//服務器套接字private ServerSocket server;//客戶機套接字private Socket socket;void start() {//啟動服務器try {server = new ServerSocket(8998);//服務器啟動8998端口System.out.println("服務器套接字已經創建成功");while(true) {System.out.println("等待客戶機的連接");socket = server.accept();//服務器監聽客戶機連接BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//根據套接字字節流創建字符輸入流while(true) {//循環接收信息String message = reader.readLine();//讀取一行文字if("exit".equals(message)) {//入過客戶機發來的內容為"exit"System.out.println("客戶機退出");break;//停止接收信息}System.out.println("客戶機:"+message);}reader.close();//關閉流socket.close();//關閉套接字}}catch(IOException e) {e.printStackTrace();}}public static void main(String[] args) {// TODO Auto-generated method stubMyServer tcp = new MyServer();tcp.start();//啟動服務器}}

結果:

運行服務器端程序,將輸出提示信息,等待客戶呼叫。下面再來看一下客戶端程序。

編寫客戶端程序,將用戶在文本框中輸入的信息發送至服務器端,并將文本框中輸入的信息顯示在客戶端的文本域中。

package Package21;import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;public class MyClient extends JFrame {private PrintWriter writer;//根據套接字字節流創建的字符輸出流Socket socket;//客戶端套接字private JTextArea area = new JTextArea();//展示信息的文本private JTextField text = new JTextField();//發送信息的文本框public MyClient() {setTitle("向服務器送數據");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);Container c = getContentPane();//著容器JScrollPane scrollPane = new JScrollPane(area);//滾動面板getContentPane().add(scrollPane,BorderLayout.CENTER);c.add(text,"South");//將文本框放置在文本的下部text.addActionListener(new ActionListener() {//文本框觸發回車事件public void actionPerformed(ActionEvent e) {writer.println(text.getText().trim());//將文本框中的信息寫入流area.append(text.getText()+"\n");將文本框中的信息顯示在文本域中text.setText("");//將文本框清空}});}private void connect() {//連接服務器方法area.append("嘗試連接\n");//文本域中提示信息try {socket = new Socket("127.0.0.1",8998);//連接本地計算機的8998端口writer = new PrintWriter(socket.getOutputStream(),true);area.append("完成連接\n");}catch(IOException e) {e.printStackTrace();}}public static void main(String[] args) {// TODO Auto-generated method stubMyClient clien = new MyClient();clien.setSize(200,200);//窗體大小clien.setVisible(true);//顯示窗體clien.connect();//連接服務器}}

結果:

說明

當一臺機器上安裝了多個網絡應用程序時,很可能指定的端口號已被占用。還可能遇到以前運行良好的網絡程序突然運行不了的情況,這種情況很可能也是由于端口被別的程序占用了。此時可以運行netstat-help來獲得幫助,使用netstat-an命令來查看該程序所使用的端口

21.3 UDP程序

用戶數據報協議(UDP)是網絡信息傳輸的另一種形式。基于UDP的通信和基于TCP的通信不同,基于UDP的信息傳遞更快,但不提供可靠性保證。使用UDP傳遞數據時,用戶無法知道數據能否正確地到達主機,也不能確定到達目的地的順序是否和發送的順序相同。雖然UDP是一種不可靠的協議,但如果需要較快地傳輸信息,并能容忍小的錯誤,可以考慮使用UDP。

基于UDP通信的基本模式如下:

  1. 將數據打包(稱為數據包),然后將數據包發往目的地。

  2. 接收別人發來的數據包,然后查看數據包。

發送數據包的步驟如下:

(1)使用DatagramSocket()創建一個數據包套接字。

(2)使用DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)創建要發送的數據包。

(3)使用DatagramSocket類的send()方法發送數據包。

接收數據包的步驟如下:

(1)使用DatagramSocket(int port)創建數據包套接字,綁定到指定的端口。

(2)使用DatagramPacket(byte[] buf, int length)創建字節數組來接收數據包。

(3)使用DatagramPacket類的receive()方法接收UDP包。

注意

DatagramSocket類的receive()方法接收數據時,如果還沒有可以接收的數據,在正常情況下receive()方法將阻塞,一直等到網絡上有數據傳來,receive()方法接收該數據并返回。如果網絡上沒有數據發送過來,receive()方法也沒有阻塞,肯定是程序有問題,大多數情況下是因為使用了一個被其他程序占用的端口號。

21.3.1 DatagramPacket類

java.net包的DatagramPacket類用來表示數據包。DatagramPacket類的構造方法如下:

  1. DatagramPacket(byte[] buf, int length)。
  2. DatagramPacket(byte[] buf, int length, InetAddress address, int port)。

第一種構造方法在創建DatagramPacket對象時,指定了數據包的內存空間和大小。第二種構造方法不僅指定了數據包的內存空間和大小,還指定了數據包的目標地址和端口。在發

送數據時,必須指定接收方的Socket地址和端口號,因此使用第二種構造方法可創建發送數據的DatagramPacket對象。

21.3.2 DatagramSocket類

java.net包中的DatagramSocket類用于表示發送和接收數據包的套接字。該類的構造方法如下:

  1. DatagramSocket()。
  2. DatagramSocket(int port)。
  3. DatagramSocket(int port, InetAddress addr)。

第一種構造方法創建DatagramSocket對象,構造數據報套接字,并將其綁定到本地主機任何可用的端口上。第二種構造方法創建DatagramSocket對象,創建數據報套接字,并將其綁定到本地主機的指定端口上。第三種構造方法創建DatagramSocket對象,創建數據報套接字,并將其綁定到指定的端口和指定的本地地址上。第三種構造函數適用于有多塊網卡和多個IP地址的情況。

如果接收數據時必須指定一個端口號,不允許系統隨機產生,此時可以使用第二種構造方法。比如有個朋友要你給他寫信,那他的地址就必須確定,不確定是不行的。在發送數據時通常使用第一種構造方法,不指定端口號,而是系統為我們分配一個端口號,就像寄信不需要到指定的郵局去寄一樣。

21.3.3 UDP網絡程序設計

根據前面所講的網絡編程的基本知識以及UDP網絡編程的特點,下面創建一個廣播數據報程序。廣播數據報是一項較新的技術,其原理類似于電臺廣播。廣播電臺需要在指定的波段和頻率上廣播信息,收聽者也要將收音機調到指定的波段、頻率,才可以收聽廣播內容。

【例21.3】創建UDP協議廣播電臺程序

package Package21;import java.io.IOException;
import java.net.*;public class Notification extends Thread {String weather = "節目預報:八點有大型晚會,請收聽";int port = 9898;InetAddress iaddress = null;MulticastSocket socket = null;@SuppressWarnings("deprecation")Notification(){try {iaddress = InetAddress.getByName("224.255.10.0");//數字不能用中文數字socket = new MulticastSocket(port);socket.setTimeToLive(1);socket.joinGroup(iaddress);}catch(IOException e) {e.printStackTrace();}}public void run() {while(true) {DatagramPacket packet = null;byte data[] = weather.getBytes();packet = new DatagramPacket(data,data.length,iaddress,port);System.out.println(weather);try {socket.send(packet);sleep(3000);}catch(IOException e) {e.printStackTrace();}catch(InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {Notification W = new Notification();W.start();}
}

接收廣播程序。單擊“開始接收”按鈕,系統開始接收主機播出的信息;單擊“停止接收”按鈕,系統停止接收廣播主機播出的信息。代碼如下:

package Package21;import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;public class Receive extends JFrame implements Runnable,ActionListener{int port;InetAddress group = null;MulticastSocket socket = null;JButton inceBtn = new JButton("開始接收");JButton stopBtn = new JButton("停止接收");JTextArea inceAr = new JTextArea(10,10);JTextArea inced = new JTextArea(10,10);Thread thread;boolean stop = false;public Receive() {setTitle("廣播數據報");setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);thread = new Thread(this);inceBtn.addActionListener(this);stopBtn.addActionListener(this);inceAr.setForeground(Color.blue);JPanel north = new JPanel();north.add(inceBtn);north.add(stopBtn);add(north,BorderLayout.NORTH);JPanel center = new JPanel();center.setLayout(new GridLayout(1,2));center.add(inceAr);center.add(inced);add(center,BorderLayout.CENTER);validate();port = 9898;try {group = InetAddress.getByName("224.255.10.0");socket = new MulticastSocket(port);socket.joinGroup(group);}catch(IOException e) {e.printStackTrace();}setBounds(100,50,360,380);setVisible(true);}public void run() {while(!stop) {byte data[] = new byte[1024];DatagramPacket packet = null;packet = new DatagramPacket(data,data.length,group,port);try {socket.receive(packet);String message = new String(packet.getData(),0,packet.getLength());inceAr.setText("正在接收的內容:\n"+message);inced.append(message+"\n");}catch(IOException e) {e.printStackTrace();}}}public void actionPerformed(ActionEvent e) {if(e.getSource()==inceBtn) {inceBtn.setBackground(Color.red);stopBtn.setBackground(Color.yellow);if(!(thread.isAlive())) {thread = new Thread(this);}thread.start();stop = false;}if(e.getSource() == stopBtn) {inceBtn.setBackground(Color.yellow);stopBtn.setBackground(Color.red);stop = true;}}public static void main(String[] args) {// TODO Auto-generated method stubReceive rec = new Receive();rec.setSize(460,200);}}

結果:

說明

發出廣播和接收廣播的主機地址必須位于同一個組內,地址范圍為224.0.0.0~224.255.255.255,該地址并不代表某個特定主機的位置。加入同一個組的主機可以在某個端口上廣播信息,也可以在某個端口上接收信息。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/206724.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/206724.shtml
英文地址,請注明出處:http://en.pswp.cn/news/206724.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據采集工具的大全【都是免費值得收藏】

數據是推動業務成功的關鍵之一。為了獲取準確、全面的信息,數據采集成為了許多企業和個人的必備工作。本文將專注于數據采集工具,探討其在全網和指定網站采集方面的優勢,為大家提供對比分析,以幫助大家找到最適合的數據采集利器。…

算法復習——6種排序方法的簡單回顧

算法復習——6種排序方法的簡單回顧 常見排序方法:冒泡排序、選擇排序、插入排序、堆排序、歸并排序、快速排序的簡單回顧 冒泡排序 重復“從序列右邊開始比較相鄰兩個數字的大小,再根據結果交換兩個數字的位置” 在冒泡排序中,第 1 輪需要比較 n - 1…

Tair(1):Tair介紹

1 介紹 ? 在Tair出現之前的很長一段時間里,像redis、memcache這些知名NoSql數據庫是不支持分布式的,在這樣的背景下,由淘寶網自主開發并在2010.6開源的一個高性能、高擴展、高可靠分布式緩存,類似map的key/value結構&#xff0c…

使用單例模式+觀察者模式實現參數配置實時更新

使用vector存儲觀察者列表 #include <iostream> #include <vector> #include <functional> #include <algorithm>// 配置參數結構體 struct MyConfigStruct {int parameter1;std::string parameter2; };class Config { public:using Observer std::f…

hive 命令行中使用 replace 和nvl2 函數報錯

1.有時候在命令行的情況下使用 replace 函數時會報錯 這個時候可以使用 translate 代替 2.有時候使用 nvl2() 函數的時候會報錯 這個時候可以用 case when 來代替

【Spring 源碼】 深入理解 Bean 定義之 BeanDefinition

&#x1f680; 作者主頁&#xff1a; 有來技術 &#x1f525; 開源項目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 倉庫主頁&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 歡迎點贊…

兩數之和問題

更好的閱讀體驗請點擊 兩數之和。 題目&#xff1a;兩數之和 ? 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 ? 你可以假設每種輸入只會對應一個答案。但是&#xff…

MetricBeat監控Redis

目錄 一、安裝部署 二、開啟Redis監控模塊 三、編輯Redis配置文件 四、啟動Metricbeat 五、查看監控圖表 一、安裝部署 metriceat的安裝部署參考章節&#xff1a; 監控組件>Metricbeat安裝使用&#xff0c;這里不再贅述。 二、開啟Redis監控模塊 進入metricbeat安裝目錄…

【每日一題】出租車的最大盈利

文章目錄 Tag題目來源解題思路方法一&#xff1a;遞歸方法二&#xff1a;遞歸記錄數組記憶化搜索方法三&#xff1a;動態規劃&#xff08;遞推&#xff09; 寫在最后 Tag 【遞歸】【記憶化搜索】【動態規劃】【數組】【2023-12-08】 題目來源 2008. 出租車的最大盈利 解題思路…

【EI會議征稿中】2024年第四屆人工智能、自動化與高性能計算國際會議(AIAHPC 2024)

2024年第四屆人工智能、自動化與高性能計算國際會議&#xff08;AIAHPC 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Automation and High Performance Computing 2024第四屆人工智能、自動化與高性能計算國際會議(AIAHPC 2024)將于20…

藍橋杯從零開始備戰(Python組)---基礎知識篇

第一次嘗試報名藍橋杯的Python組&#xff0c;好好備戰&#xff0c;希望省賽可以拿獎&#xff01;目前是整理了一些Python的常用函數和常用內置庫&#xff0c;后面可能會開始刷題&#xff0c;如果有比較需要記住的知識點&#xff0c;會再寫一篇刷題篇 一、輸入輸出 1.輸入字符…

游戲被攻擊怎么辦

隨著科技的進步和互聯網的普及&#xff0c;游戲行業也正在經歷前所未有的變革。玩家們不再滿足于傳統的線下游戲&#xff0c;而是轉向了線上游戲。然而&#xff0c;隨著游戲的線上化&#xff0c;游戲安全問題也日益凸顯。游戲受到攻擊是游戲開發者永遠的痛點&#xff0c;談“D“…

HomeAssistant添加HACS插件并實現公網控制米家,HomeKit等智能家居

HomeAssistant添加HACS插件并實現公網控制米家&#xff0c;HomeKit等智能家居 文章目錄 HomeAssistant添加HACS插件并實現公網控制米家&#xff0c;HomeKit等智能家居基本條件一、下載HACS源碼二、添加HACS集成三、綁定米家設備 ? 上文介紹了如何實現群暉Docker部署HomeAssist…

【嵌入式開發 Linux 常用命令系列 4.1 -- git push 遠程分支與本地分支查看】

文章目錄 概述git push 語法步驟1&#xff1a;git 遠程主機名查看步驟2&#xff1a;git 遠程分支名查看步驟3&#xff1a;git 本地分支名查看示例演示 概述 在日常工作中&#xff0c;將代碼 git clone 本地之后&#xff0c;或者使用repo init && repo sync 之后不知道…

SQLserver截取字符串

當我們存的數據是json的時候可以全部取出在模糊查詢但是有多個重復數據的時候就沒辦法準確的模糊出來這個時候我們就需要用的字符串截取 --創建函數create FUNCTION [dbo].[Fmax] (str varchar(50),start VARCHAR(50),length VARCHAR(50)) RETURNS varchar(max) AS BEGINDEC…

商品詳情頁評論和評論列表評論的排序html代碼

以下是一個簡單的商品詳情頁的 HTML 代碼示例&#xff1a; <!DOCTYPE html> <html> <head><title>商品詳情頁</title><style>/* CSS 樣式可以在這里添加 */</style> </head> <body><h1>商品詳情頁</h1><…

7-1 查找書籍

給定n本書的名稱和定價&#xff0c;本題要求編寫程序&#xff0c;查找并輸出其中定價最高和最低的書的名稱和定價。 輸入格式: 輸入第一行給出正整數n&#xff08;<10&#xff09;&#xff0c;隨后給出n本書的信息。每本書在一行中給出書名&#xff0c;即長度不超過30的字…

條碼生成器與Zint使用

文章目錄 目的條形碼zint支持條形碼種類下載編譯qt pro配置code保存條形碼目的 1: 了解條形碼數據理論知識 2: 了解zint第三方庫相關, 如何編譯引用到項目中 條形碼 條形碼(Barcode)一維碼 和二維碼(QR code)都是用于存儲信息的圖形化表示方式,通常應用于商品標識、庫…

無頭瀏覽器與Selenium:探索無界爬蟲的奇妙世界

selenium設置無頭瀏覽器 背景 ? 我們之前的selenium都是瀏覽器驅動自動打開一個網頁&#xff0c;執行相關操作&#xff0c;其實也可以讓其后臺顯示&#xff0c;不用在前臺顯示。 ? 要設置無頭瀏覽器&#xff0c;可以使用Selenium的Headless模式。在Headless模式下&#xf…

鴻蒙(HarmonyOS)應用開發——web組件

簡述 在開發的工作中&#xff0c;可能存在一個場景&#xff0c;我們有一個問卷調查的h5頁面&#xff0c;需要切入到app 中。這個時候&#xff0c;就需要從app 端操作&#xff0c;切換到web端操作。不管是安卓、ios、小程序都提供有web組件。那么harmonyos 中也提供web組件來在…