java 网络编程

Posted 玛丽莲茼蒿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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类

以上是关于java 网络编程的主要内容,如果未能解决你的问题,请参考以下文章

电脑JAVA环境变量如何设置

Java编程中必须了解 十几个代码段

如何在Java中的ArrayList末尾附加元素?

Java 负数 indexOf (从末尾计数 [length()] )

java 19.从列表末尾删除第N个节点(#)。java

java 19.从列表末尾删除第N个节点(#)。java