JAVA學(xué)習(xí)筆記06——網(wǎng)絡(luò)編程基礎(chǔ)

JAVA學(xué)習(xí)筆記06——網(wǎng)絡(luò)編程基礎(chǔ)

網(wǎng)絡(luò)相關(guān)概念

  • 網(wǎng)絡(luò)通信

    • 概念:兩臺設(shè)備之間通過網(wǎng)絡(luò)實現(xiàn)數(shù)據(jù)傳輸
    • 網(wǎng)絡(luò)通信:將數(shù)據(jù)通過網(wǎng)絡(luò)從一臺設(shè)備傳輸?shù)搅硪慌_設(shè)備
    • Java.net包下提供了一系列的類或接口,供程序員使用,完成網(wǎng)絡(luò)通信
  • 網(wǎng)絡(luò):

    • 概念:兩臺或多臺設(shè)備通過一定物理設(shè)備連接起來構(gòu)成了網(wǎng)絡(luò)
    • 根據(jù)網(wǎng)絡(luò)的覆蓋范圍不同,對網(wǎng)絡(luò)進(jìn)行分類:
      • 局域網(wǎng)
      • 城域網(wǎng)
      • 廣域網(wǎng)
  • ip地址:

    • 概念:用于唯一標(biāo)識網(wǎng)絡(luò)中的每臺計算機(jī)/主機(jī)

    • 查看ip地址:ipconfig

    • ip表示:

      • 點分十進(jìn)制

      • 對于IPv4用4個字節(jié)(32位)表示

      0~255 0~255 0~255 0~255
    • ip地址的組成=網(wǎng)絡(luò)地址+主機(jī)地址,比如:192.168.1.1

    • IPv6是互聯(lián)網(wǎng)工程任務(wù)組設(shè)計的用于替代IPv4的下一代IP協(xié)議

    • IPv4地址分類:

      • A類:0.0.0.0到127.255.255.255
      • B類:128.0.0.0到191.255.255.255
      • C類:192.0.0.0到223.255.255.255
      • D類:224.0.0.0到239.255.255.255
      • E類:240.0.0.0到247.255.255.255

域名和端口

域名

  • 例如:www.baidu.com
  • 好處:為了方便記憶,解決記IP地址困難的問題
  • 概念:將IP地址映射成域名,HTTP協(xié)議

端口號

  • 概念:用于標(biāo)識計算機(jī)上某個特定的網(wǎng)絡(luò)程序
  • 表示形式:以整數(shù)形式,范圍0~65535
  • 0~1024已經(jīng)被占用,比如ssh 22,ftp 21,smtp 25,http 80
  • 常見的網(wǎng)絡(luò)程序端口號:
    • tomcat 8080
    • mysql 3306
    • oracle 1521
    • sqlserver:1433

網(wǎng)絡(luò)協(xié)議

  • 協(xié)議是網(wǎng)絡(luò)編程中數(shù)據(jù)的組織形式

  • OSI模型(理論) TCP/IP模型 TCP/IP模型各層對應(yīng)協(xié)議
    應(yīng)用層 應(yīng)用層 HTTP、ftp、telnet、DNS……
    表示層
    會話層
    傳輸層 傳輸層(TCP) TCP、UDP……
    網(wǎng)絡(luò)層 網(wǎng)絡(luò)層(IP) IP、ICMP、ARP……
    數(shù)據(jù)鏈路層 物理+數(shù)據(jù)鏈路層 Link
    物理層

TCP和UDP

  • TCP傳輸控制協(xié)議
    • TCP/IP(Transmission Control Protocol/Internet Protocol)的簡寫。
    • 中文譯名為傳輸控制協(xié)議/因特網(wǎng)互聯(lián)協(xié)議,又叫網(wǎng)絡(luò)通訊協(xié)議,這個協(xié)議是Internet最基本的協(xié)議,簡單地說,就是由網(wǎng)絡(luò)層的IP協(xié)議和傳輸層的TCP協(xié)議組成的
    • 使用TCP協(xié)議前,須先建立TCP連接,形成傳輸數(shù)據(jù)通道
    • 傳輸前,采用”三次握手“方式,是可靠的
    • TCP協(xié)議進(jìn)行通信的兩個應(yīng)用進(jìn)程:客戶端、服務(wù)端
    • 在連接中可進(jìn)行大數(shù)據(jù)量的傳輸
    • 傳輸完畢,需釋放已建立連接,效率低
  • UDP協(xié)議
    • 將數(shù)據(jù)、源、目的封裝成數(shù)據(jù)包,不需要建立連接
    • 每個數(shù)據(jù)包的大小限制在64K以內(nèi),不適合傳輸大量數(shù)據(jù)
    • 因無需連接,所以是不可靠的
    • 發(fā)送數(shù)據(jù)結(jié)束時無需釋放資源(因為不是面向連接的),速度快

InetAddress類

相關(guān)方法

  • 獲取本機(jī)InetAddress對象getLocalHost
  • 根據(jù)指定主機(jī)名、域名獲取ip地址對象getByName
  • 獲取InetAddress對象的主機(jī)名getHostName
  • 獲取InetAddress對象的地址getHostAddress
import java.net.InetAddress;
import java.net.UnknownHostException;

public class API {
    public static void main(String[] args) throws UnknownHostException {
        // 獲取本機(jī)的InetAddress對象
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);

        // 根據(jù)指定主機(jī)名獲取InetAddress對象
        InetAddress host1 = InetAddress.getByName("DESKTOP-CQHA3I8");
        System.out.println("host1 = " + localHost);

        // 根據(jù)域名返回InetAddress對象
        InetAddress  host2 = InetAddress.getByName("www.baidu.com");
        System.out.println("host2 = " + host2);

        // 通過InetAddress對象,獲取對應(yīng)的地址
        String host2Address = host2.getHostAddress();
        System.out.println("host2地址:" + host2Address);

        // 通過InetAddress對象,獲得主機(jī)名或域名
        String host2Name = host2.getHostName();
        System.out.println("host2主機(jī)名/域名:" + host2Name);
    }
}

Socket

  • 基本介紹:
    • 套接字(Socket)開發(fā)網(wǎng)絡(luò)應(yīng)用程序被廣泛采用,以至于成為事實上的標(biāo)準(zhǔn)
    • 通信的兩端都要由Socket,是兩臺機(jī)器間通信的端點
    • 網(wǎng)絡(luò)通信其實就是Socket間的通信
    • Socket允許把網(wǎng)絡(luò)連接當(dāng)成一個流,數(shù)據(jù)在兩個Socket間通過IO傳輸。
    • 一般主動發(fā)起通信的應(yīng)用程序?qū)倏蛻舳?,等待通信請求的為服?wù)端
    • 當(dāng)我們需要通訊時(讀寫數(shù)據(jù))
      • socket.getOutputStream()
      • socket.getInputStream()
    • Socket有TCP編程和UDP編程

TCP網(wǎng)絡(luò)通信編程

  • 基本介紹

    • 基于客戶端—服務(wù)端的網(wǎng)絡(luò)通信
    • 底層使用的時TCP/IP協(xié)議
    • 應(yīng)用場景舉例:客戶端發(fā)送數(shù)據(jù),服務(wù)端接受并顯示
    • 基于Socket的TCP編程
  • 案例:

    // 服務(wù)端
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SocketServer {
        public static void main(String[] args) throws IOException {
            // 在9999接口監(jiān)聽,等待連接
            ServerSocket serverSocket = new ServerSocket(9999);
            System.out.println("等待連接……");
            // 當(dāng)沒有客戶端連接時,程序阻塞,等待連接
            Socket socket = serverSocket.accept();
            System.out.println("服務(wù)端 socket = " + socket.getClass());
            // 讀取客戶端寫入數(shù)據(jù)通道的數(shù)據(jù)
            InputStream inputStream = socket.getInputStream();
            byte[] buf = new byte[1024];
            int readLen = 0;
            while ((readLen = inputStream.read(buf)) != -1) {
                System.out.println(new String(buf, 0, readLen));
            }
            // 關(guān)閉流和socket
            inputStream.close();
            socket.close();
        }
    }
    
    // 客戶端
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    
    public class SocketTCPClient {
        public static void main(String[] args) throws IOException {
            // 連接服務(wù)器,如果連接成功,返回Socket對象
            Socket socket = new Socket(InetAddress.getLocalHost(),9999);
            System.out.println("客戶端 socket = " + socket.getClass());
            // 連接上后,生成Socket,通過socket.getOutputStream()得到和Socket對象關(guān)聯(lián)的輸出流對象
            OutputStream outputStream = socket.getOutputStream();
    
            outputStream.write("hello server".getBytes(StandardCharsets.UTF_8));
            socket.shutdownOutput();
            // 關(guān)閉流和Socket對象,必須關(guān)閉
            outputStream.close();
            socket.close();
            System.out.println("Socket關(guān)閉");
        }
    }
    
  • 應(yīng)該設(shè)置一個結(jié)束標(biāo)記,說明結(jié)束發(fā)送數(shù)據(jù)。socket.shutdownOutput()

  • 案例,網(wǎng)絡(luò)上傳文件

    // 服務(wù)端
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPFileCopyServer {
        public static void main(String[] args) throws IOException {
            // 1.服務(wù)端在本機(jī)8888端口監(jiān)聽
            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("服務(wù)端在8888");
            // 2.等待連接
            Socket socket = serverSocket.accept();
            // 3.讀取客戶端發(fā)送的數(shù)據(jù)
            //   通過socket得到輸入流
            BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
            ByteArrayOutputStream bos = new ByteArrayOutputStream();// 創(chuàng)建輸出流對象
            byte[] b = new byte[1024];// 字節(jié)數(shù)組
            int len;
            while ((len = bufferedInputStream.read(b)) != -1) {// 循環(huán)讀取
                bos.write(b, 0, len);// 把讀取到的數(shù)據(jù)寫入bos
            }
            byte[] array = bos.toByteArray();// 然后將bos 轉(zhuǎn)成字節(jié)數(shù)組
            bos.close();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("C:\\Users\\46429\\Pictures\\qie233.GIF"));
            bufferedOutputStream.write(array);
            bufferedOutputStream.close();
            bufferedInputStream.close();
            
            socket.close();
            serverSocket.close();
        }
    }
    
    // 客戶端
    import java.io.*;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class TCPFileCopyClient {
        public static void main(String[] args) throws IOException {
    
            // 客戶端連接服務(wù)端,得到Socket對象
            Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
            // 創(chuàng)建讀取磁盤文件的輸入流
            String filePath = "C:\\Users\\46429\\Pictures\\qie.GIF";
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
            ByteArrayOutputStream bos = new ByteArrayOutputStream();// 創(chuàng)建輸出流對象
            byte[] b = new byte[1024];// 字節(jié)數(shù)組
            int len;
            while ((len = bufferedInputStream.read(b)) != -1) {// 循環(huán)讀取
                bos.write(b, 0, len);// 把讀取到的數(shù)據(jù)寫入bos
            }
            byte[] array = bos.toByteArray();// 然后將bos 轉(zhuǎn)成字節(jié)數(shù)組
            bos.close();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
            bufferedOutputStream.write(array);
            bufferedInputStream.close();
            bufferedOutputStream.close();
            socket.shutdownOutput();
        }
    }
    

netstat指令

  • netstat -an 可以查看當(dāng)前主機(jī)網(wǎng)絡(luò)情況,包括端口監(jiān)聽情況和網(wǎng)絡(luò)連接情況

  • netstat -an|more可以分頁顯示

  • 要求在dos控制臺下執(zhí)行win + r

  • netstat.png
  • 說明:

    • Listening表示某個端口在監(jiān)聽
    • 如果有一個外部程序(客戶端)連接到該端口,就會顯示一條連接信息
    • 可以輸入ctrl+c退出指令
  • netstat -anb 查看使用端口的程序,需要使用管理員權(quán)限

TCP注意點

  • 客戶端連接到服務(wù)器端后,實際上客戶端也是通過一個端口和服務(wù)端進(jìn)行通訊的,這個端口時TCP/IP來分配的,是隨機(jī)的。

UDP網(wǎng)絡(luò)編程

基本介紹

  • 類DatagramSocket和DatagramPacket(數(shù)據(jù)包/數(shù)據(jù)報)實現(xiàn)了基于UDP協(xié)議網(wǎng)絡(luò)程序
  • UDP數(shù)據(jù)報通過數(shù)據(jù)報(數(shù)據(jù)包)套接字DatagramSocket發(fā)送和接收,系統(tǒng)不保證UDP數(shù)據(jù)報一定能夠安全送達(dá)目的地,也不能確定什么時候可以抵達(dá)。
  • DatagramPacket對象封裝了UDP數(shù)據(jù)報,在數(shù)據(jù)報中包含了發(fā)送端的IP地址和端口號以及接受端的IP地址和端口號
  • UDP協(xié)議中每個數(shù)據(jù)報都給出了完整的地址信息,因此無需建立發(fā)送方和接收方的連接

UDP網(wǎng)絡(luò)編程基礎(chǔ)流程

  • 核心的兩個類/對象DatagramSocket與DatagramPacket
  • 建立發(fā)送端,接收端
  • 建立數(shù)據(jù)包
  • 調(diào)用DatagramSocket的發(fā)送、接受方法
  • 關(guān)閉DatagramSocket

UDP說明

  • 沒有明確的服務(wù)端和客戶端,演變成數(shù)據(jù)的發(fā)送端和接收端
  • 接收數(shù)據(jù)和發(fā)送數(shù)據(jù)是通過DatagramSocket對象完成
  • 將數(shù)據(jù)封裝到DatagramPacket對象/裝包
  • 當(dāng)接受到DatagramPacket對象,需要進(jìn)行拆包,取出數(shù)據(jù)
  • DatagramSocket可以指定在哪個端口接收數(shù)據(jù)

應(yīng)用案例

  • 編寫一個接收端A,和一個發(fā)送端B
  • 接收端A在9999端口等待接受數(shù)據(jù)(receive)
  • 發(fā)送端B向接收端A發(fā)送數(shù)據(jù)“hello,明天吃火鍋”
  • 接收端A接收到發(fā)送端B發(fā)送的數(shù)據(jù),回復(fù)“好的,明天見”再退出
  • 發(fā)送端接收回復(fù)的數(shù)據(jù),再退出
// 接收端A
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;

public class UDPReceiverA {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建一個DatagramSocket對象,準(zhǔn)備接受數(shù)據(jù)
        DatagramSocket socket = new DatagramSocket(9999);
        byte[] buf = new byte[1024];// 一個數(shù)據(jù)包最大64k
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        // 調(diào)用接收方法
        System.out.println("接收端A接受數(shù)據(jù)。。。");
        socket.receive(packet);

        int length = packet.getLength();
        byte[] data = packet.getData();
        String s = new String(data, 0, length);
        System.out.println(s);

        byte[] response = "彳亍".getBytes(StandardCharsets.UTF_8);
        DatagramPacket rPacket = new DatagramPacket(response, response.length, InetAddress.getByName("172.25.225.69"), 9998);
        socket.send(rPacket);
        // 關(guān)閉資源
        socket.close();
        System.out.println("A端退出");
    }
}
// 發(fā)送端B
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;

public class UDPSenderB {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(9998);
        // 將發(fā)送的數(shù)據(jù)封裝到packet對象
        byte[] data = "明天吃火鍋?。?!".getBytes(StandardCharsets.UTF_8);
        DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("172.25.225.69"), 9999);
        socket.send(packet);

        byte[] response = new byte[1024];
        DatagramPacket rPacket = new DatagramPacket(response,response.length);
        System.out.println("接收A端數(shù)據(jù)。。。");
        socket.receive(rPacket);
        byte[] bRe = rPacket.getData();
        String re = new String(bRe, 0,rPacket.getLength());
        System.out.println(re);
        System.out.println("ok");

        socket.close();
        System.out.println("B端退出");
    }
}

個人總結(jié)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容