java 网络编程

一、InetAddress类

1.2 常用方法

实例化

构造器全部隐藏,对外只提供静态方法进行对象的实例化

InetAddress inet2 = InetAddress.getByName("www.baidu.com");

注意: IP的实例化和File的实例化一样,无论实际有没有这个IP,我都能实例化出一个对象

getLocalHost():静态方法,返回本机地址对象

InetAddress localHost = InetAddress.getLocalHost();

其他常用方法

getHostName()
getHostAddress()

二、TCP和UDP编程

记忆点:

1. TCP使用流套接字;UDP使用数据报套接字

2. 对于客户端:TCP在套接字的构造器里给出服务器端的IP和端口号;UDP的套接字构造器用空参的,在数据报中给出

3. 对于服务器:TCP和UDP都在套接字的构造器指定端口号,这一点是一致的

4. TCP基于字节,用I/O流的read()和write()方法;UDP用send()和receive()方法

5. TCP的read()方法和UDP的receive()方法都是阻塞式的。但是他们结束阻塞的标志是不同的!!!

        read方法结束阻塞的条件:①读到文件末尾 ②发送方程序终止,断开连接 ③发送方端socket用shutdownOutput方法告诉read我写完了

        

        receive方法结束阻塞的条件:收到一个packet

        

6. TCP的accept方法也是阻塞的,如果只开server,没有client去连接的话,server一直转圈圈原因是阻塞在了accept上,并不是read上。

        

2.1 常用类和方法

Socket类

1. 构造方法

流套接字要在构造器里给出服务器端的IP和端口号

new Socket(InetAddress.getByName("localhost"), 5566);

2. getgetOutputStream() 获取输出流

3. getInputStream()获取输入流

 这里socket可以调用getOutputStream()和getInputStream()方法是因为TCP是面向字节流的。

serverSocket类

1. 构造方法

只需要指明自己开放的端口号就可以

new ServerSocket(5566);

2. accept()方法

接收来自客户端的Scoket,并return一个socket实例。

该方法监听并accept客户端的请求,The method blocks until a connection is made 

Socket socket = serverSocket.accept(); 

DatagramSocket类

DatagramPacket类

2.2 TCP编程实例1

要求:客户端发送内容给服务器,服务器将内容打印到控制台上。

        下图是我们应该刻在脑子里的图,socket只提供端服务,要区分socket和socket.getInputStream()得到的流

        

  • 因为TCP以字节流的方式传送数据,而题目又要求我们将接收到的字符打印到控制台上,这是一个字节流->字符流的转换。可以用转换流,这里我们用的是ByteArraryOutputStream类,该类维护了一个很大的byte数组,这样就不用担心一个3字节的字符被“劈开”输出乱码了。
package TCP;

import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPtest {
    @Test
    public void client(){
        Socket socket = null;
        OutputStream os = null;
        try {
            //1. 创建一个socket对象,指明服务器的IP和端口号
            socket = new Socket(InetAddress.getByName("localhost"), 5566); //socket

            //2. socket获取一个输出流,用于发送数据
            os = socket.getOutputStream(); //流

            //3.发送数据
            os.write("你好,我是客户端。今天是隔离第2天,睡了9个小时,属实是有点多了。".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if(os!=null)
                try {
                    os.close();  //关闭流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if(socket!=null)
                try {
                    socket.close(); //socket也是一种资源,使用完也要关闭
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 服务器把接收到的信息输入到控制台
     */
    @Test
    public void server(){
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        ByteArrayOutputStream byteArrayOs = null;
        try {
            //1. 创建客户端的serverSocket,指明开启的端口号
            serverSocket = new ServerSocket(5566);

            //2.接收客户端,并返回一个socket
            socket = serverSocket.accept(); //监听并accept客户端的请求,The method blocks until a connection is made
            System.out.println("收到了来自:" + socket.getInetAddress().getHostName() + "的数据");

            //3. socket获取输入流
            inputStream = socket.getInputStream();

            //4. 读取来自client的数据
            //错误写法:这样写有的字符被拆开,会导致乱码
//            int len;
//            byte []b = new byte[4];
//            while((len = inputStream.read(b)) != -1){
//                System.out.println(new String(b,0,len));
//            }

            //正确写法:可以使用转换流将字节转换成字符
            //这里我们使用另一种方法:ByteArrayOutputStream
            int len;
            byteArrayOs = new ByteArrayOutputStream();
            byte []b = new byte[4];
            while((len = inputStream.read(b)) != -1){
                byteArrayOs.write(b,0,len);  //将读取出来的[]b写到ByteArrayOutputStream类维护的一个大数组里
            }
            System.out.println(byteArrayOs.toString());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(byteArrayOs != null){
                try {
                    byteArrayOs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

先运行server程序,再运行client程序。

而实际应用中服务器的程序应该用一个while循环一直开着,

package TCP;

import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPtest {
    @Test
    public void client(){
        Socket socket = null;
        OutputStream os = null;
        try {
            //1. 创建一个socket对象,指明服务器的IP和端口号
            socket = new Socket(InetAddress.getByName("localhost"), 5566); //socket

            //2. socket获取一个输出流,用于发送数据
            os = socket.getOutputStream(); //流

            //3.发送数据
            os.write("你好,我是客户端".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if(os!=null)
                try {
                    os.close();  //关闭流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if(socket!=null)
                try {
                    socket.close(); //socket也是一种资源,使用完也要关闭
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 服务器把接收到的信息输入到控制台
     */
    @Test
    public void server(){
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        ByteArrayOutputStream byteArrayOs = null;
        try {
            //1. 创建客户端的serverSocket,指明开启的端口号
            serverSocket = new ServerSocket(5566);

            while(true){
                //2.等到客户端建立连接,并返回一个socket
                socket = serverSocket.accept(); //监听并accept客户端的请求,The method blocks until a connection is made
                System.out.println("收到了来自:" + socket.getInetAddress().getHostName() + "的数据");

                //3. socket获取输入流
                inputStream = socket.getInputStream();

                //这里我们使用另一种方法:ByteArrayOutputStream
                int len;
                byteArrayOs = new ByteArrayOutputStream();
                byte []b = new byte[4];
                while((len = inputStream.read(b)) != -1){
                    byteArrayOs.write(b,0,len);  //将读取出来的[]b写到ByteArrayOutputStream类维护的一个大数组里
                }
                System.out.println(byteArrayOs.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(byteArrayOs != null){
                try {
                    byteArrayOs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

先开启服务器,再开启客户端,等客户端发送完毕断开连接再开启一次客户端

 如果要想和下面介绍的UDP一样,不仅服务器持续接收,客户端也能持续发送,经尝试TCP是做不到的。

 下面给出client尝试的代码,server和上文一样

package TCP;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

/**
 * 实现Client持续发送,server持续接收
 */
public class Client {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream os = null;
        try {
            //1. 创建一个socket对象,指明服务器的IP和端口号
            socket = new Socket(InetAddress.getByName("localhost"), 5566); //socket

            //2. socket获取一个输出流,用于发送数据
            os = socket.getOutputStream(); //流

            Scanner scanner = new Scanner(System.in);
            while(true){
                String s = null;
                if(scanner.hasNextLine()){
                    s = scanner.nextLine();
                    //3.发送数据
                    os.write(s.getBytes());
                }
                if(s.equals("bye")){
                    break;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if(os!=null)
                try {
                    os.close();  //关闭流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if(socket!=null)
                try {
                    socket.close(); //socket也是一种资源,使用完也要关闭
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}

 

 

2.3 TCP编程实例2

要求:客户端发送文件给服务器,服务器将文件保存在本地(用户在QQ空间上传照片,照片由腾讯服务器保存在本地)

package TCP;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPtest2 {
    /**
     * 客户端发送一个本地文件
     */
    @Test
    public void client(){
        Socket socket = null;
        OutputStream outputStream = null;
        BufferedInputStream inputStream = null;
        try {
            //1.创建一个socket对象,指明服务器的IP和端口号
            socket = new Socket(InetAddress.getByName("localhost"), 5566);

            //2.socket获取一个输出流
            outputStream = socket.getOutputStream();

            //3.发送数据
            inputStream = new BufferedInputStream(new FileInputStream("pic.png"));
            int len;
            byte buffer[] = new byte[1024];
            while((len = inputStream.read(buffer)) != -1){
                outputStream.write(buffer);  //发送数据给服务器
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭资源
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 服务器接收客户端发来的文件,并保存到服务器本地
     */
    @Test
    public void server(){
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        BufferedOutputStream outputStream = null;
        try {
            //1.创建一个serverSocket对象,指明服务开启的端口号
            serverSocket = new ServerSocket(5566);

            //2.接收客户端,并返回一个socket
            socket = serverSocket.accept();

            //3.socket获取输入流
            inputStream = socket.getInputStream();

            //4.读取来自客户端的文件,存储到本地
            File file = new File("./pic-1.png"); //存储到当前module下
            outputStream = new BufferedOutputStream(new FileOutputStream(file));
            int len;
            byte buffer[] = new byte[1024];
            while((len = inputStream.read(buffer)) != -1){  //读取来自客户端的文件
                outputStream.write(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5.关闭资源
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

先运行server再运行client

2.4 TCP编程实例3

要求:从客户端发送文件给服务器,服务器保存在本地。并返回“发送成功”给客户端。

  • 这其实涉及到一个“进程同步机制”,client运行到一半后先停止等待,等server完成回复的动作后,再继续执行

        

        具体到代码中,是下图这样的        ​​​​​

 但并没有用到“同步”的代码(类似于wait,notify的代码),那么是如何实现同步的呢?答案是,client端的第二个read方法阻塞住了,迫使client停止等待。

  • 如果不加下面这一句代码。server和client会陷入互相等待的死锁。因为server使用了read方法,而read方法是一个阻塞式方法,会一直开启着等待客户端的输入。而client的第二个read又等着server的回复,双方就陷入了死锁

 

问题:client明明给server传完文件了,server的read为什么还阻塞read等待输入?

回答:因为client端的文件被打碎成了流用write传输过来,如果read读的文件是本身,还能读到结束符,然后解除阻塞。但此时server的read根本不知道write写完了没有,所以要在client端加一个shutdownOutput方法告诉read我写完了。

问题:client的第一个read方法,怎么不阻塞等待呢?

回答:因为client的read是读取本地文件的,读到末尾会返回一个-1,满足read解除阻塞的条件。

问题:server发给client的回复write是一串字符串,和第一个问题一样,也没有告诉client我写完了没有(测试过),为什么client的第二个read不阻塞?

回答:因为server端write完以后整个程序结束了,直接断开连接,发送方断开连接也是read接触阻塞的充分条件之一。

package TCP;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPtest3 {
    /**
     * 客户端
     * 1)发送一个本地文件
     * 2)接收服务器发来的回复
     */
    @Test
    public void client(){
        Socket socket = null;
        OutputStream outputStream = null;
        BufferedInputStream inputStream = null;
        try {
            //1.创建一个socket对象,指明服务器的IP和端口号
            socket = new Socket(InetAddress.getByName("localhost"), 5566);

            //2.socket获取一个输出流
            outputStream = socket.getOutputStream();

            //3.发送数据
            inputStream = new BufferedInputStream(new FileInputStream("pic.png"));
            int len;
            byte buffer[] = new byte[1024];
            while((len = inputStream.read(buffer)) != -1){
                outputStream.write(buffer);  //发送数据给服务器
            }

            socket.shutdownOutput();

            //4.接收服务的回复,并打印到控制台
            InputStream inputStream1 = socket.getInputStream();
            ByteArrayOutputStream byteArrayOs = new ByteArrayOutputStream();
            while((len = inputStream1.read(buffer)) != -1){
                byteArrayOs.write(buffer,0,len); //将buffer的内容写到ByteArrayOutputStream维护的大数组里
            }
            System.out.println(byteArrayOs.toString());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭资源
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 服务器
     * 1)接收客户端发来的文件,并保存到服务器本地
     * 2)回复客户端
     */
    @Test
    public void server(){
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        BufferedOutputStream outputStream = null;
        try {
            //1.创建一个serverSocket对象,指明服务开启的端口号
            serverSocket = new ServerSocket(5566);

            //2.接收客户端socket
            socket = serverSocket.accept();

            //3.socket获取输入流
            inputStream = socket.getInputStream();

            //4.读取来自客户端的文件,存储到本地
            File file = new File("./pic-2.png"); //存储到当前module下
            outputStream = new BufferedOutputStream(new FileOutputStream(file));
            int len;
            byte buffer[] = new byte[1024];
            while((len = inputStream.read(buffer)) != -1){  //读取来自客户端的文件
                outputStream.write(buffer);
            }

            //5.回复客户端
            OutputStream outputStream1 = socket.getOutputStream();
            outputStream1.write("我已收到".getBytes());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5.关闭资源
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果:

2.5 UDP编程实例1

要求:客户端给服务器发送字符串,服务器打印在显示屏上。

package UDP;

import org.junit.Test;

import java.io.IOException;
import java.net.*;

public class UDPtest {
    @Test
    public void client() throws IOException {
        //1.创建一个数据报套接字对象
        DatagramSocket socket = new DatagramSocket();

        //2.创建一个数据报对象,并指明服务器的IP和端口号
        byte [] data = "你好我是客户端,今天要努力学习哦".getBytes();
        DatagramPacket packet = new DatagramPacket(data,0, data.length, InetAddress.getLocalHost(),5566);

        //3.套接字发送数据报
        socket.send(packet);

        //4.关闭资源
        socket.close();
    }

    @Test
    public void server() throws IOException {
        //1.创建服务器端的套接字对象
        DatagramSocket socket = new DatagramSocket(5566);

        //2.创建服务器端的数据报对象
        byte []data = new byte[1024];
        DatagramPacket packet = new DatagramPacket(data, 0, data.length);

        //3.套接字接收数据报
        socket.receive(packet);

        //4. 关闭资源
        socket.close();
        System.out.println(new String(packet.getData()) );
    }
}

2.6 UDP编程实例2

要求:实现发送端持续发送,接收端持续接收

注意,此段代码是错误示范
package UDP;

import org.junit.Test;

import java.io.*;
import java.net.*;
import java.util.Scanner;

public class UDPtest2 {

    @Test
    public void client() throws IOException {
        //1.创建一个数据报套接字对象
        DatagramSocket socket = new DatagramSocket();

        byte []data = new byte[1024];
        while(true){
            //读取控制台数据,存到data中
            int len = System.in.read(data);
            //2.创建一个数据报对象,并指明服务器的IP和端口号
            DatagramPacket packet = new DatagramPacket(data,0, len, InetAddress.getLocalHost(),5566);
            //3.套接字发送数据报
            socket.send(packet);
            String s = new String(data,0,data.length);
            if(s.equals("bye")){
                break;
            }
        }
       //4.关闭资源
        socket.close();
    }

    @Test
    public void server() throws IOException {
        //1.创建服务器端的套接字对象
        DatagramSocket socket = new DatagramSocket(5566);


        while(true){
            //2.创建服务器端的数据报对象
            byte []data = new byte[1024];
            DatagramPacket packet = new DatagramPacket(data, 0, data.length);
            //3.套接字接收数据报
            socket.receive(packet);
            System.out.println(new String(packet.getData()) );

            if(packet.getData().toString().equals("bye")){
                break;
            }
        }

        //4. 关闭资源
        socket.close();
    }
}

运行出现问题!控制台没法输入。怀疑不是程序的问题,而是没有main方法就不能从控制台输入

void main(String[] args)

 写了一个肯定正确的单元测试测试了一下:

 @Test
    public void testSystemIn(){
        Scanner scanner = new Scanner(System.in);
        if(scanner.hasNextLine()){
            String s = scanner.nextLine();
            System.out.println(s);
        }
    }

发现这个单元测试也没法输入,看来确实不是程序的问题。 

现在我们把代码从单元测试中拿出来,给发送端和接收端分别写一个类

package UDP;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;

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

        byte []data = new byte[1024];
        while(true){
            //接收控制台输入,存入data
            int len = System.in.read(data);
            //2.创建一个数据报对象,并指明服务器的IP和端口号
            DatagramPacket packet = new DatagramPacket(data,0, len, InetAddress.getLocalHost(),5566);
            //3.套接字发送数据报
            socket.send(packet);
            String s = new String(data,0,data.length);
            if(s.equals("bye")){
                break;
            }
        }
        //4.关闭资源
        socket.close();
    }
}
package UDP;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Receiver {
    public static void main(String[] args) throws IOException {
        //1.创建服务器端的套接字对象
        DatagramSocket socket = new DatagramSocket(5566);


        while(true){
            //2.创建服务器端的数据报对象
            byte []data = new byte[1024];
            DatagramPacket packet = new DatagramPacket(data, 0, data.length);
            //3.套接字接收数据报
            socket.receive(packet);
            System.out.println(new String(packet.getData()) );

            if(packet.getData().toString().equals("bye")){
                break;
            }
        }

        //4. 关闭资源
        socket.close();
    }
}

一定要注意:

之所以要这样做,是因为read方法不改变数组的长度,data数组进入read方法之前长度(data.length)是1024,从read方法出来后,依然是1024。 

 OK!成功

 

关于命令行输入的逻辑,以上代码想的是System.in是字节流,发送的数据报刚好也是字节流,那直接读进来呀。之前还讲过两种方法

法(一):BufferedReader的readLine()方法

那这里为什么可以使用data.length了呢?经过下面的测试我们发现,getBytes方法会改变数组的长度,所以直接用data.length就可以。

 

 

 法(二):我们再用Scanner作为输入试一下,也是可以的

 

三、URL编程

记忆点

  1. 原来“种子”就是URL啊。怪不得以前网盘保存了种子,几年后下载不了资源了。因为服务器那边不提供了。
  2. 其实之前在ES项目里用过URL编程

3.1 常用方法

URL类

 3.2 URL下载网络资源

package URL;

import org.junit.Test;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class URLtest {
    /**
     * 将网上一张图片保存到本地
     */
    @Test
    public void test(){
        HttpURLConnection urlConnection = null;
        InputStream inputStream = null;
        BufferedOutputStream outputStream = null;
        try {
            //1.创建URL对象
            URL url = new URL("https://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%253A%252F%252Fp0.itc.cn%252Fq_70%252Fimages03%252F20210906%252F7355e6b25ac348f8891ff4d97476926c.jpeg%26refer%3Dhttp%253A%252F%252Fp0.itc.cn%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Dauto%3Fsec%3D1669691277%26t%3D3ba3c915bd2eadf87d25492472b0cea4&thumburl=https%3A%2F%2Fimg1.baidu.com%2Fit%2Fu%3D3022682180%2C2626045641%26fm%3D253%26fmt%3Dauto%26app%3D120%26f%3DJPEG%3Fw%3D550%26h%3D309");
           
            //2.创建urlConnection对象
            urlConnection = (HttpURLConnection) url.openConnection();

            //3.连接
            urlConnection.connect();

            //4.连接上后就可以获取流了
            inputStream = urlConnection.getInputStream();

            outputStream = new BufferedOutputStream(new FileOutputStream(new File("shirley杨.jpeg")));
            int len;
            byte []buffer = new byte[1024];
            while((len = inputStream.read(buffer)) != -1){
                outputStream.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5.关闭资源
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(urlConnection != null){
                urlConnection.disconnect();
            }
        }
    }
}

运行结果:

这一段代码的作用和下图是一样的(浏览器下载是非断点下载,刚好我们用的BufferedOutputStream也是非断点下载,可以说是一模一样了,只不过浏览器前端可能用的不是纯java而是js实现的??)

PS:断点下载的实现用RandomAccessFile类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值