Java網絡編程

1、網絡編程三要素

一、IP地址

  • 設備在網絡中的地址,是惟一標識

二、端口

  • 應用程序在設備中的惟一標識

三、協議

  • 數據在網絡中傳輸的規則,常見的協議有UDP協議和TCP協議

2、IP地址

一、含義

  • IP地址,全稱爲Internet Protocol Address,網絡協議地址。是分配給上網設備的數字標籤。
  • 常見的IP分類有ipv4和ipv6

二、實踐--終端ping網址

  • 在終端輸入 ping www.itheima.com的過程解析

三、分類

ipv4:32bit來表示java

  • 問題:ipv4能分配的地址數量最多爲256的四次方個,約爲42億,數量逐漸不夠使用

ipv6:128bit來表示編程

四、相關命令(Mac)

  • 查看本機的IP地址數組

    • ifconfig
    • ifconfig | grep net 用管道符號+grep命令來過濾一下,更方便查看
  • 檢查網絡是否連通(還能夠肯定域名的IP地址)安全

    • ping IP地址

五、特殊IP

  • 127.0.0.1:回送地址,本地迴環地址。能夠表明本機的IP地址,通常用來測試使用

六、Java中的InetAddress類

6.一、含義服務器

  • 表示IP地址

6.二、經常使用方法網絡

  • static InetAddress getByName("String host"):經過主機名獲取InetAdress對象,host能夠是主機名,也能夠是IP地址
  • String getHostName():獲取主機名
  • String getHostAddress():獲取IP地址

6.三、關於Mac查看和修改主機名和計算機名socket

https://www.jianshu.com/p/dbf2fa105f26tcp

3、端口

一、含義

  • 應用程序在設備中的惟一表示

二、端口號

  • 用兩個字節表示的整數來標識。範圍0~25535
  • 0~1023之間的端口號經常使用於一些知名的網絡服務或應用,咱們本身使用1024及以上

三、注意

  • 一個端口號只能被一個應用程序來使用

4、協議

一、UDP協議

  • UDP(User Datagram Protocol)用戶數據報協議測試

  • 面向無鏈接:只管發送,沒必要先創建鏈接,均可以發送成功。若是二者已經鏈接,就能成功接收;3d

  • 特色

    • 速度快
    • 大小限制:最大爲64K
    • 數據不安全,易丟失
  • 常見場景:音視頻、普通數據

二、TCP協議

  • TCP(Transmission Control Protocol)傳輸控制協議
  • 面向鏈接:先保證鏈接已經創建,才傳輸數據
  • 特色
    • 速度慢
    • 沒有大小限制
    • 數據安全
  • 經常使用場景:聊天

5、UDP通訊程序

一、發送端

  • 過程圖示

  • 代碼實現
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //1.找碼頭
        DatagramSocket ds = new DatagramSocket();

        //2.打包數據
        String message = "你好哇,李婷婷!";
        byte[] bytes = message.getBytes();
        InetAddress address = InetAddress.getByName("127.0.0.1");
        int port = 10000;
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);

        //3.發送數據
        ds.send(dp);

        //4.釋放資源
        ds.close();
    }
}

二、接收端

  • 過程圖示

  • 代碼實現
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //1.找碼頭    ---表示從10000端口號接收數據,不然就是從隨機端口接收數據
        DatagramSocket ds = new DatagramSocket(10000);

        //2.建立包
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        //3.接受包
        ds.receive(dp);

        //4.打開包獲得數據
        byte[] data = dp.getData();
        System.out.println(new String(data));

        //5.釋放資源
        ds.close();
    }
}

三、實現通訊

  • 先運行接收端,保證創建了鏈接。
  • 再運行發送端,發送數據
  • 檢查服務端,確實收到了數據

四、注意

  1. 若是接收端沒有收到數據,就會死等(阻塞)。能夠在接收先後加上輸出語句來驗證
  2. 新數組接收到的數據中,若是不能填滿,會包含空格,可使用getLength()來獲取數據的長度

其實,數組data是多餘的,直接用bytes也能夠獲得數據

五、UDP三種通訊方式

5.一、單播:

  • 一對一發送
  • 以前寫的代碼就是單播通訊

5.二、組播

  • 一對多發送,可是多個接收端要是一組的

  • 代碼實現

組播地址:244.0.0.0 ~ 244.255.255.255 。其中244.0.0.0 ~ 244.0.0.255是預留的組播地址

 

5.三、廣播

  • 一對全部發送

  • 代碼實現

6、TCP通訊程序

一、TCP通訊原理

  • TCP通訊協議是一種可靠的網絡協議,因此在通訊兩端各創建一個Socket對象

  • 通訊以前,要保證創建鏈接

  • 經過socket產生IO流來進行通訊

二、TCP發送數據的步驟

①、建立客戶端Socket對象,與指定的服務端鏈接

②、獲取輸出流,寫出數據

③、釋放資源

  • 代碼實現以下
public class ClientDemo {
    public static void main(String[] args) throws IOException {

        Socket socket = new Socket("127.0.0.1", 10000);

        OutputStream os = socket.getOutputStream();
        os.write("xian".getBytes());

        os.close();
        socket.close();
    }
}

//注意:此時若是咱們運行,是會報異常ConnectException,由於沒法和接收端創建鏈接

三、TCP接受數據

①、建立服務端Socket對象(ServerSocket)

②、監聽客戶端,返回一個Socket對象

③、獲取輸入流,讀數據,把數據顯示在控制檯

④、釋放資源

  • 代碼實現
public class ServerDemo {
    public static void main(String[] args) throws IOException {

        ServerSocket ss = new ServerSocket(10000);

        System.out.println(111);
        Socket accept = ss.accept();//等待客戶端來進行鏈接,一直等待
        System.out.println(222);

        //複習
        InputStream is = accept.getInputStream();
        int b;
        while ((b = is.read() )!= -1){
            System.out.println((char) b);
        }
        
        is.close();
        ss.close();
    }
}

四、原理分析

  • 須要先運行服務端,服務端會執行到 ss.accept()處等待客戶端鏈接
  • 客戶端鏈接,發送數據
  • 服務端接受收據

注意

  • accept()方法是阻塞的,做用:等待客戶端鏈接
  • 客戶端鏈接服務器經過:三次握手

下面的類比就尼瑪離譜,公平打在有才上

  • 針對客戶端,往外寫,用輸出流;針對服務端,往裏讀,用輸入流
  • read()方法是阻塞的
  • os.close()會附帶一個結束標記,來讓read結束
  • socket.close()關閉鏈接經過:四次揮手

五、練習一

客戶端:發送數據,接受服務端反饋

服務端:接收數據,給出反饋

客戶端代碼

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //建立socket對象
        Socket socket = new Socket("127.0.0.1", 10086);

        //獲取輸出流,寫出數據
        OutputStream os = socket.getOutputStream();
        os.write("hello".getBytes());
        socket.shutdownOutput();//關閉輸出流,寫一個結束標記給接收端,不會關閉socket

        //獲取輸入流,讀入數據
        /*
        InputStream is = socket.getInputStream();
        int b;
        while ((b = is.read()) != -1){
            System.out.println((char) b);
        }
        */
        //由於接受的是中文,用字節流會亂碼,socket又沒有字符流,--->用緩衝流
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }

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

    }
}

服務端代碼

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //建立socket對象
        ServerSocket ss = new ServerSocket(10086);

        //監聽客戶端,返回一個Socket對象
        Socket accept = ss.accept();

        //獲取輸入流,讀入數據
        InputStream is = accept.getInputStream();
        int b;
        while ((b = is.read()) != -1){
            System.out.println((char) b);
        }

        //獲取輸出流,寫出數據
        /*OutputStream os = accept.getOutputStream();
        os.write("你誰啊".getBytes());*/
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        bw.write("你誰啊?");

        //關閉資源
        bw.close();
        is.close();
        ss.close();
    }
}

六、練習二

客戶端:將文件上傳到服務器,接受服務器的反饋

服務器:接受客戶端上傳的文件,上傳完畢後給出反饋

客戶端代碼

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //建立socket
        Socket socket = new Socket("127.0.0.1", 10086);

        //本地流,讀取本地文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("heima/ClientDir/java圖標.jpg"));

        //網絡中的流,寫到服務器
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);

        int b;
        while ((b = bis.read()) != -1){
            bos.write(b);
        }

        socket.shutdownOutput();//給服務器一個結束標記,表名傳輸完畢

        //獲取服務端數據
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }

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

服務端代碼

public class ServerDemo {
    public static void main(String[] args) throws IOException {

        //建立socket
        ServerSocket ss = new ServerSocket(10086);
        //等待鏈接
        Socket accept = ss.accept();

        //網絡中的流,讀取客戶端數據
        BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
        //本地的流,持久化
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("heima/ServerDir/copy.jpg"));
        //讀取,持久化到本地
        int b;
        while ((b = bis.read()) != -1){
            bos.write(b);
        }

        //發送反饋信息
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        bw.write("上傳成功");
        bw.newLine();
        bw.flush();

        //關閉資源
        ss.close();
        accept.close();//網絡中的流,隨着socket的關閉也會關閉
        bos.close();
    }
}
相關文章
相關標籤/搜索