Java 网络编程 Ⅰ

news2024/11/24 18:30:15

目录

    • 基础知识
      • IP 和 Port
      • internet(互联网)
    • Java UDP 编程
      • UDP(User Datagram Protocol):``无连接无状态的数据报通讯协议``
      • 实现
    • Java TCP 编程
      • TCP(Transmission Control Protocol):``面向连接的通讯协议``
      • 实现
    • Java HTTP 编程
      • HTTP(Hyper Text Transfer Protocol):``超文本传输协议``
      • 访问流程
      • 实现

基础知识

  • 计算机通讯:数据从一个 IP 的 port 出发(发送方),运输到另一个 IP 的 port (接收方)

IP 和 Port

  • 每一个计算机设备上都有若干个 网卡,每一个网卡上有 (全球唯一)单独硬件地址,MAC地址,每个网卡/机器都有一个或多个 IP 地址

  • 查看本机器(计算机)的 IP 地址

    • 运行 cmd,打开 命令行工具

    • 输入 ipconfig(Window 系统)

    • 输入 ifconfig(Linux/Mac 系统)

    在这里插入图片描述

  • 保留 IP :127.0.0.1(代表 本机)

  • port:端口(逻辑上的)

    • 范围:0~65535

    • 0~1023,OS 已经占有,80 是 Web,23 是 telnet

    • 1024~65535,任和一个程序都可以使用(注意:一个端口一次只能被一个程序使用)

    • 查询(端口号使用情况):

      • 运行 cmd,打开 命令行工具

      • 输入 netstat -an(Window/Linux/Mac 上都是)

      在这里插入图片描述
      在这里插入图片描述

  • 两台机器(电脑)的通讯就是在:IP+Port 上进行的

internet(互联网)

  • 公网(万维网、互联网)与 内网(局域网)

    • 网络是分层的,最外层是公网,底下的每层都是内网

    • 而,IP 地址可以在每个层次的网重用

  • tracert 命令:查看当前机器和目标机器的访问中继

    • 运行 cmd,打开 命令行工具

    • 输入 tracert [目标机器的 IP]

    在这里插入图片描述

  • TCP/IP 四层网络概念模型协议分组

    • 应用层:HTTP、TFTP、FTP、NFS、WAIS、SMTP、DNS、TeInet、SNMP、…

    • 传输层:TCP、UDP

    • 网络层:IP、ICMP、OSPF、EIGRP、IGMP

    • 数据链路层:ARP、RARP、…

    请添加图片描述

  • HTTP:超文本传输协议,是现在广为流行的 WEB 网络的基础。

  • ICMP(Internet Control Message Protocol,网络控制消息协议)是 TCP/IP 的核心协议之一,用于在 IP 网络中发送控制消息,提供通信过程中的各种问题反馈。

    • ICMP 直接使用 IP 数据包传输,但 ICMP 并不被视为 IP 协议的子协议。

    • 而,常见的联网状态诊断工具依赖于 ICMP 协议。

  • TCP:传输控制协议,是一种面向连接的,可靠的,基于字节流传输的通信协议。TCP 具有端口号的概念,用来标识同一个地址上的不同应用。

  • UDP:用户数据报协议,是一个面向数据报的传输层协议,是不可靠的。同 TCP 一样有用来标识本地应用的端口号。

Java UDP 编程

UDP(User Datagram Protocol):无连接无状态的数据报通讯协议

  • 用户数据报协议面向数据报地无连接通讯协议(发送方发送消息后,如果接收方不在目的地,那这个消息就丢失了)

  • 不保证可靠的数据传输(发送方无法得知是否发送成功)

  • 速度快,也可以在较差的网络下使用(好处是:简单、节省、经济)

实现

  • DatagramSocket:通讯的数据管道

    • send 和 receive 方法

    • (可选,多网卡)绑定一个 IP 和 Port

  • DatagramPacket

    • 集装箱:封装数据

    • 地址标签:目的地 IP + Port

  • 注意:无主次之分,但是为了成功接受信息,要求接收方必须早于发起方运行

/**
 * 数据 发送 与 接收 测试
 */
public class Main {
    public static void main(String[] args) throws IOException {
        new Thread(() -> {
            // 先启动 接收方
            try {
                UdpInternet.takeOver(3001);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
        String str1 = "hello world";
        new Thread(() -> {
            try {
                UdpInternet.send(str1, "127.0.0.1", 3001);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

/**
 * UDP 网络编程
 */
public class UdpInternet {

    /**
     * 接受数据
     *
     * @param port 端口号
     */
    public static void takeOver(int port) throws IOException {
        // 管道
        DatagramSocket socket = new DatagramSocket(port);
        byte[] bytes = new byte[1024];
        // 数据集装箱
        DatagramPacket packet = new DatagramPacket(bytes, 1024);
        System.out.println("UdpInternet.takeOver 正在接收消息!");
        System.out.println("接收端的地址 = " + socket.getLocalSocketAddress());
        // 接收消息,无限等待
        socket.receive(packet);
        System.out.println("UdpInternet.takeOver 接收到消息!");
        System.out.println("数据:" + new String(packet.getData(), 0, packet.getLength()));
        System.out.println("发送端的地址 = " + packet.getSocketAddress());
    }

    /**
     * 发送数据(端口没有指定)
     *
     * @param str  消息
     * @param ip   IP
     * @param port 端口号
     */
    public static void send(String str, String ip, int port) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        DatagramPacket packet = new DatagramPacket(str.getBytes(), str.length(), InetAddress.getByName(ip), port);
        System.out.println("UdpInternet.send 正在发送消息!");
        socket.send(packet);
        System.out.println("UdpInternet.send 消息发送完成!");
    }

}

Java TCP 编程

TCP(Transmission Control Protocol):面向连接的通讯协议

  • 传输控制协议

  • 两台机器的可靠无差错的数据传输

  • 双向字节流传递

实现

  • 第一步:服务器创建一个 ServerSocket ,等待连接

  • 第二步:客户机创建一个 Socket ,连接到服务器

  • 第三步:ServerSocket 接收到连接,创建一个 Socket 和客户机的 Socket 建立专线连接,后续服务器和客户机的对话(这一对 Socket)会在一个单独的线程(服务器端)上进行

  • 第四步:服务端的 ServerSocket 继续等待连接(可以连接多个客户机),如果有连接请求,就执行 第二步

  • ServerSocket:服务器码头

    • 需要绑定 port

    • 如果有多块网卡,需要再绑定一个 IP 地址

  • Socket:运输通道

    • 客户端需要绑定服务器的地址和 port

    • 客户端往 Socket 输入流写入数据,送到服务端

    • 客户端从 Socket 输出流获取服务器端传过来的数据

    • 服务器亦要如此

  • Test

/**
 * TCP 测试
 */
public class ServerTest {

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

        // 创建服务器
        new Thread(() -> {
            try {
                TcpServer server = new TcpServer(8001);
                // 单线程
                // server.openInterface();
                // 多线程
                TcpServer.openInterface(server);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

    }
}

/**
 * TCP 测试
 */
public class ClientTest1 {

    public static void main(String[] args) throws IOException {
        // 客户端连接服务器
        new Thread(() -> {
            try {
                TcpClient.connect("127.0.0.1", 8001);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

    }
}

/**
 * TCP 测试
 */
public class ClientTest2 {

    public static void main(String[] args) throws IOException {
        // 客户端连接服务器
        new Thread(() -> {
            try {
                TcpClient.connect("127.0.0.1", 8001);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

  • Client
/**
 * TCP 客户端
 */
public class TcpClient {

    /**
     * 连接 服务端
     *
     * @param ip   主机 IP
     * @param port 端口号
     * @throws IOException IO异常
     */
    public static void connect(String ip, int port) throws IOException {
        // 创建 连接
        Socket socket = new Socket(InetAddress.getByName(ip), port);
        // 开启输入流、输出流
        // 开启 通道的输入流,并包装为 缓存,方便 读入
        // 客户端的输入流是:服务端的 回应
        InputStream is = socket.getInputStream();
        BufferedReader input = new BufferedReader(new InputStreamReader(is));
        // 开启 通道的输出流,并包装为 数据输出流,方便传输
        // 输出数据给 服务端
        OutputStream os = socket.getOutputStream();
        DataOutputStream output = new DataOutputStream(os);

        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (socket.isConnected()) {
            System.out.println("客户端 请输入(quit 结束):");
            // 读取键盘输入
            String read = reader.readLine();
            if ("quit".equalsIgnoreCase(read)) {
                break;
            } else {
                // 发送数据给服务器(在数据后加上系统的分隔符)
                output.writeBytes(read + System.getProperty("line.separator"));
                // 获取 服务器返回的 信息
                System.out.println("Server 说: " + input.readLine());
            }
        }
        // 关闭 输出流
        output.close();
        // 关闭 输入流
        input.close();
        // 关闭 键盘输入
        reader.close();
        // 关闭连接
        socket.close();
    }
}

  • Server
/**
 * TCP 服务端
 */
public class TcpServer {

    /**
     * 码头
     */
    private static ServerSocket serverSocket;

    /**
     * 构造函数
     * <p>
     * 创建 服务器连接 码头
     *
     * @param port 端口号
     * @throws IOException IO异常
     */
    public TcpServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    /**
     * 创建供客户端连接的端口(多线程式)
     *
     * @throws IOException IO异常
     */
    public static void openInterface(TcpServer server) {
        try {
            ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
            while (true) {
                // 等待 客户端 请求连接
                Socket accept = serverSocket.accept();
                System.out.println("来了一个 Client!");
                executor.submit(new Thread(new Worker(accept, server)));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建供客户端连接的端口(单线程式)
     *
     * @throws IOException IO异常
     */
    public void openInterface() throws IOException {
        // 等待 客户端 请求连接
        Socket accept = serverSocket.accept();
        openInterface(accept);
    }

    /**
     * 创建供客户端连接的端口(单线程式)
     *
     * @throws IOException IO异常
     */
    public void openInterface(Socket accept) throws IOException {
        // 开启 通道的输入流,并包装为 缓存,方便 读入
        // 服务端的输入流是:客户端的 输出
        InputStream is = accept.getInputStream();
        BufferedReader input = new BufferedReader(new InputStreamReader(is));
        // 开启 通道的输出流
        // 输出数据给 客户端
        OutputStream os = accept.getOutputStream();
        DataOutputStream output = new DataOutputStream(os);

        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (accept.isConnected()) {
            // 获取 客户器发过来的 信息
            // 不知道有什么方法可以检测到 客户端 连接已断开,就 先不管吧!!!!!!!!!!
            // 虽然 报错
            System.out.println("Client 说: " + input.readLine());

            System.out.println("服务端 回话(Finish 结束):");
            // 读取键盘输入
            String read = reader.readLine();
            if ("Finish".equalsIgnoreCase(read)) {
                break;
            } else {
                // 发送数据给客户端
                output.writeBytes(read + System.getProperty("line.separator"));
            }
        }
        // 关闭 输出流
        output.close();
        // 关闭 输入流
        input.close();
        // 关闭 键盘输入
        reader.close();
        // 关闭连接
        accept.close();
    }
}

/**
 * 工厂
 */
class Worker implements Runnable {

    Socket socket;

    TcpServer server;

    public Worker(Socket socket, TcpServer server) {
        this.socket = socket;
        this.server = server;
    }

    @Override
    public void run() {
        try {
            server.openInterface(socket);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Java HTTP 编程

HTTP(Hyper Text Transfer Protocol):超文本传输协议

  • 而,HTTPS 是 HTTP 的加密安全版本

  • HTTP 协议通过 TCP 传输,HTTP 默认使用端口 80,HTTPS 使用 443

访问流程

  • 在浏览器输入 URL 地址(如:https://www.baidu.com)

  • 浏览器将连接到远程服务器上(IP+80Port)

  • 请求下载一个 HTML 文件下来,放到本地临时文件夹中

  • 在浏览器显示出来

  • 注意:HTTP(超文本传输协议)、HTML(超文本标记语言)

实现

/**
 * HTTP 测试(GET、POST)
 */
public class HttpTest {

    public static void main(String[] args) {
        try {
            // GET
            // 要访问的 url 地址
            String urlName = "https://www.baidu.com";
            // 封装
            URL url = new URL(urlName);
            System.out.println("GET 连接获得的内容:" + HttpTest.doGet(url));

            // POST
            // 封装
            String urlString = "https://tools.usps.com/go/ZipLookupAction.action";
            Object userAgent = "HTTPie/0.9.2";
            Object redirects = "1";
            // cookie 接收策略,全部接收
            CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
            Map<String, String> params = new HashMap<>(3);
            params.put("tAddress", "1 Market Street");
            params.put("tCity", "San Francisco");
            params.put("sState", "CA");
            String result = doPost(new URL(urlString), params,
                    userAgent == null ? null : userAgent.toString(),
                    redirects == null ? -1 : Integer.parseInt(redirects.toString()));
            System.out.println("POST 连接获得的内容:" + result);


        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    /**
     * 模拟 GET 方法
     *
     * @param url 封装好的 url
     * @return 内容
     * @throws IOException IO异常
     */
    public static String doGet(URL url) throws IOException {

        // 打开连接(获得 URL 连接)
        URLConnection connection = url.openConnection();
        // 建立连接
        connection.connect();

        System.out.println("====== 打印 http 的头部信息 ======");
        Map<String, List<String>> headerFields = connection.getHeaderFields();
        headerFields.forEach(
                (key, value1) -> value1.stream().map(value -> key + ":" + value).forEach(System.out::println));

        System.out.println("====== 输出收到的内容 属性信息 ======");
        System.out.println("内容类型:" + connection.getContentType());
        System.out.println("内容长度:" + connection.getContentLength());
        System.out.println("内容编码:" + connection.getContentEncoding());
        System.out.println("日期:" + connection.getDate());
        System.out.println("过期:" + connection.getExpiration());
        System.out.println("最后修改时间:" + connection.getLastModified());

        // 以 UTF-8 的编码包装,读取 输入流
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
        StringBuilder result = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            result.append(line);
        }
        // 关闭 输入流
        reader.close();
        return result.toString();
    }

    /**
     * 模拟 POST 方法
     *
     * @param url            封装好的 url
     * @param nameValuePairs 参数键值对
     * @param userAgent      用户代理
     * @param redirects      重定向( >=0 false | <0 true)
     * @return 内容
     * @throws IOException IO异常
     */
    public static String doPost(URL url, Map<String, String> nameValuePairs, String userAgent, int redirects)
            throws IOException {

        // 打开连接(获得 URL 连接)
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 设置请求属性
        if (userAgent != null) {
            connection.setRequestProperty("User-Agent", userAgent);
        }
        // 设置设置实例 是否 跟随重定向
        if (redirects >= 0) {
            connection.setInstanceFollowRedirects(false);
        }
        // 打开 输出流
        connection.setDoOutput(true);

        // 输出请求参数
        try (PrintWriter out = new PrintWriter(connection.getOutputStream())) {
            boolean first = true;
            for (Map.Entry<String, String> pair : nameValuePairs.entrySet()) {
                // 参数之间有一个 '&' 字符用于拼接
                if (first) {
                    first = false;
                } else {
                    out.print('&');
                }
                // 参数输出格式为:'key'='value'&'key1'='value1'
                out.print(pair.getKey());
                out.print('=');
                out.print(URLEncoder.encode(pair.getValue(), StandardCharsets.UTF_8));
            }
        }
        // 获取内容编码,如果 为空,则 设为 UTF-8
        String encoding = connection.getContentEncoding();
        if (encoding == null) {
            encoding = "UTF-8";
        }
        if (redirects > 0) {
            // 响应码
            int responseCode = connection.getResponseCode();
            System.out.println("responseCode = " + responseCode);
            // 响应码为:301 或 302 或 303 时
            if (responseCode == HttpURLConnection.HTTP_MOVED_PERM
                    || responseCode == HttpURLConnection.HTTP_MOVED_TEMP
                    || responseCode == HttpURLConnection.HTTP_SEE_OTHER) {
                // 获取标题字段
                String location = connection.getHeaderField("Location");
                if (location != null) {
                    // url
                    URL base = connection.getURL();
                    // 断开连接
                    connection.disconnect();
                    // 重新 POST
                    return doPost(new URL(base, location), nameValuePairs, userAgent, redirects - 1);
                }
            }
        } else if (redirects == 0) {
            throw new IOException("Too many redirects");
        }

        // 获取 HTML 内容
        StringBuilder response = new StringBuilder();
        try (Scanner in = new Scanner(connection.getInputStream(), encoding)) {
            while (in.hasNextLine()) {
                response.append(in.nextLine());
                response.append("\n");
            }
        } catch (IOException e) {
            InputStream err = connection.getErrorStream();
            if (err == null) {
                throw e;
            }
            try (Scanner in = new Scanner(err)) {
                response.append(in.nextLine());
                response.append("\n");
            }
        }
        return response.toString();
    }
}

/**
 * 基于 HTTP Client(JDK 11) 的 HTTP 测试(GET、POST)
 */
public class HttpClientTest {

    public static void main(String[] args) {
        // GET
        URI baidu = URI.create("https://www.baidu.com");
        HttpResponse<String> response = doGet(baidu);
        System.out.println("GET 响应内容:" + (response != null ? response.body() : null));

        // POST
        URI usps = URI.create("https://tools.usps.com/go/ZipLookupAction.action");
        HttpResponse<String> response1 = doPost(usps, "HTTPie/0.9.2");
        System.out.println("POST 响应内容:" + (response1 != null ? response1.body() : null));
    }

    /**
     * GET 方法模拟
     *
     * @param uri URI
     * @return Http 响应<String>
     */
    public static HttpResponse<String> doGet(URI uri) {
        try {
            // 创建 HTTP 客户端
            HttpClient client = HttpClient.newHttpClient();
            // 生成 HTTP 请求
            HttpRequest request = HttpRequest.newBuilder(uri).build();
            // 客户端发送请求,返回 HTTP 应答
            return client.send(request, HttpResponse.BodyHandlers.ofString());
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * POST 方法模拟
     *
     * @param uri       URI
     * @param userAgent 用户代理
     * @return Http 响应<String>
     */
    public static HttpResponse<String> doPost(URI uri, String userAgent) {
        try {
            // 创建 HTTP 客户端
            HttpClient client = HttpClient.newBuilder().build();
            // 生成 HTTP 请求
            HttpRequest request = HttpRequest.newBuilder()
                    // URI
                    .uri(uri)
                    // 用户代理
                    .headers("User-Agent", userAgent)
                    // 内容类型
                    .header("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
                    // 参数 拼接
                    .POST(HttpRequest.BodyPublishers.ofString(
                            "tAddress=" + URLEncoder.encode("1 Market Street", StandardCharsets.UTF_8)
                                    + "&tCity=" + URLEncoder.encode("San Francisco", StandardCharsets.UTF_8)
                                    + "&sState=CA"))
                    .build();
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            System.out.println("response 响应码 = " + response.statusCode());
            System.out.println("response 标题 = " + response.headers());
            return response;
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

/**
 * 基于 HTTP Commponents(org.apache.httpcomponents) 的 HTTP 测试(GET、POST)
 * <p>
 * 是一个集成的 JAVA HTTP 工具包
 */
public class HttpComponents {

    public static void main(String[] args) {
        // GET
        HttpGet httpGet = new HttpGet("https://www.baidu.com");
        System.out.println("GET 响应内容:" + doGet(httpGet));

        // POST
        HttpPost httpPost = new HttpPost("https://tools.usps.com/go/ZipLookupAction.action");
        // POST 的请求参数
        List<BasicNameValuePair> list = new ArrayList<>();
        list.add(new BasicNameValuePair("tAddress", URLEncoder.encode("1 Market Street", StandardCharsets.UTF_8)));
        list.add(new BasicNameValuePair("tCity", URLEncoder.encode("San Francisco", StandardCharsets.UTF_8)));
        list.add(new BasicNameValuePair("sState", "CA"));
        System.out.println("POST 响应内容:" + doPost(httpPost, list, "HTTPie/0.9.2"));
    }

    /**
     * GET 方法模拟
     *
     * @param httpGet HttpGet
     * @return String
     */
    public static String doGet(HttpGet httpGet) {
        // 创建 HTTP 客户端
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 请求配置
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置连接超时
                .setConnectTimeout(5000)
                // 设置连接请求超时
                .setConnectionRequestTimeout(5000)
                // 设置套接字超时
                .setSocketTimeout(5000)
                // 启用 重定向
                .setRedirectsEnabled(true)
                .build();
        // 加入 请求配置
        httpGet.setConfig(requestConfig);
        // 获取 返回的内容
        StringBuilder result = new StringBuilder();
        try {
            // 执行 GET
            CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
            // 如果请求成功了
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                System.out.println("code:200");
                result.append(EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8));
            } else {
                System.out.println("请求失败!响应码:" + httpResponse.getStatusLine().getStatusCode());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result.toString();
    }

    /**
     * 模拟 POST 请求
     *
     * @param httpPost  HTTP post
     * @param list      请求参数键值对
     * @param userAgent 用户代理
     * @return String
     */
    public static String doPost(HttpPost httpPost, List<BasicNameValuePair> list, String userAgent) {
        // 获取 HTTP Client
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                // 设置重定向策略(松散的重定向策略)
                .setRedirectStrategy(new LaxRedirectStrategy()).build();
        // 请求配置
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置连接超时
                .setConnectTimeout(10000)
                // 设置连接请求超时
                .setConnectionRequestTimeout(10000)
                // 设置套接字超时
                .setSocketTimeout(10000)
                // 不启用 重定向
                .setRedirectsEnabled(false)
                .build();
        // 加入 请求配置
        httpPost.setConfig(requestConfig);
        // 获取 返回的内容
        StringBuilder result = new StringBuilder();
        try {
            // Url 编码的表单实体(用于装入 POST 请求的参数)
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
            // 将表单加入到 HTTP POST 中
            httpPost.setEntity(entity);
            // 加入用户代理
            httpPost.setHeader("User-Agent", userAgent);
            // 执行 POST
            HttpResponse httpResponse = httpClient.execute(httpPost);
            // 如果请求成功了
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                System.out.println("code:200");
                result.append(EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8));
            } else {
                System.out.println("Error 响应码:" + httpResponse.getStatusLine().getStatusCode());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result.toString();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/365579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

XSS注入进阶练习篇(三) XSS原型链污染

XSS原型链污染1.原型链的概念1.1 构造函数的缺点1.2 prototype 属性的作用1.3 原型链1.4 constructor属性1.5 prototype和__proto__2. 原型链污染2.1 原型链污染是什么&#xff1f;2.2 原型链污染的条件2.3 原型连污染实例2.3.1 hackit 20182.3.2 challenge-04223.总结1.原型链…

Java跳槽涨薪之路-想学Java的赶紧上车了

前言Java 是近 10 年来计算机软件发展过程中的传奇&#xff0c;在很多开发者心中的地位可谓“爱不释手”&#xff0c;与其他一些计算机语言随着时间的流逝影响也逐渐减弱不同&#xff0c;Java 随着时间的推移反而变得更加强大。按应用范围&#xff0c;Java 可分为 3 个体系&…

【Unity3D】空间和变换

1 空间 1.1 左右手坐标系及其法则 1.1.1 左右手坐标系 左手坐标系与右手坐标系Unity 局部空间、世界空间、裁剪空间、屏幕空间都采用左手坐标系&#xff0c;只有观察空间采用右手坐标系。 左右手坐标系除了坐标系朝向&#xff08;旋向性&#xff09;不同&#xff0c;还存在以…

顶象APP加固的“蜜罐”技术有什么作用

目录 蜜罐有很多应用模式 蜜罐技术让App加固攻守兼备 顶象端加固的三大功能 为了捕获猎物&#xff0c;猎人会在设置鲜活的诱饵。被诱惑的猎物去吃诱饵时&#xff0c;就会坠入猎人布置好的陷阱&#xff0c;然后被猎人擒获&#xff0c;这是狩猎中常用的一种手段。在业务安全防…

自动化测试框架设计

大数据时代&#xff0c;多数的web或app产品都会使用第三方或自己开发相应的数据系统&#xff0c;进行用户行为数据或其它信息数据的收集&#xff0c;在这个过程中&#xff0c;埋点是比较重要的一环。 埋点收集的数据一般有以下作用&#xff1a; 驱动决策&#xff1a;ABtest、漏…

华为OD机试用Python实现 -【微服务的集成测试】(2023-Q1 新题)

华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 微服务的集成测试…

信号的运算与变换

目录 前言 本章内容介绍 信号的运算与变换 相加 相乘 时移 反折 尺度变换 微分&#xff08;差分&#xff09; 积分&#xff08;累加&#xff09; 信号的奇偶求解 信号的实虚分解 合适的例题 1、时移反折 2、时移尺度 3、时移反折尺度 4、反求x(t) 前言 《信号…

gma 1.1.3 (2023.02.22) 更新日志

&#xff08;实际版本日期&#xff1a;2023.02.14&#xff09; 重要更新&#xff1a; 从本版本开始&#xff0c; gma 开始支持 Python 3.11&#xff01; 新增&#xff1a; 1、map 增加【AddDataSetDiscrete】添加离散型栅格数据集绘制功能。 2、math a、添加 Stretch 数据…

2023年PMP考试应该注意些什么?

首先注意&#xff08;报考条件&#xff09; 2023年PMP考试报名流程&#xff1a; 一、PMP英文报名&#xff1a; 英文报名时间无限制&#xff0c;随时可以报名&#xff0c;但有一年的有效期&#xff0c;所以大家尽量提前报名&#xff0c;在英文报名有效期内进行中文报名。 英…

儿童饰品发夹发卡出口美国办理什么认证?

亚马逊美国站上传新产品&#xff0c;很多时候都是需要类目审核的&#xff0c;后台给出要求提供认证&#xff0c;产品类目不同&#xff0c;所需要提供的认证证书是不一样&#xff0c;儿童产品需要提交的是CPC认证&#xff0c;玩具&#xff0c;母婴用品&#xff0c;儿童书包&…

前端面试题整理之HMTL篇(二)

HTML面试题&#xff08;二&#xff09; 前言&#xff1a; 面试题及答案解析&#xff0c;大部分来自网络整理&#xff0c;我自己做了一些简化&#xff0c;内容有很多部分已经重复&#xff0c;解释也有些乱&#xff0c;大家带着自己的思考去看&#xff0c;整理自己的语言&#x…

python中savgol_filter的详细解释

目录savgol_filter简介savgol_filter原理参数window_length对平滑的效果参数polyorder的平滑效果savgol_filter简介 Savitzky-Golay滤波器最初由Savitzky和Golay于1964年提出&#xff0c;是光谱预处理中常用滤波方法&#xff0c;它的核心思想是对一定长度窗口内的数据点进行k阶…

数据结构与算法(四):树结构

前面讲到的顺序表、栈和队列都是一对一的线性结构&#xff0c;这节讲一对多的线性结构——树。「一对多」就是指一个元素只能有一个前驱&#xff0c;但可以有多个后继。 一、基本概念 树&#xff08;tree&#xff09;是n&#xff08;n>0&#xff09;个结点的有穷集。n0时称…

魔兽世界私服架设教程—GM命令大全

如果需要什么命令可以按ctrlf查找&#xff0c;比如泰坦之握&#xff0c;就会直接定位到你想要的命令那里。橙色武器&#xff1a;85版本橙匕首&#xff0c;龙父之牙戈拉德&#xff0c;龙王之暮提里奥什&#xff0c;远古噩梦7794977950橙杖&#xff0c;可以变龙巨龙之怒&#xff…

Ae:场景编辑检测

场景编辑检测基于 Adobe Sensei 技术&#xff0c;能够自动检测已编辑剪辑中的场景变化&#xff0c;并将场景创建为标记或图层&#xff0c;以便加快项目设置。首先将素材添加到时间轴&#xff0c;然后选择一个或多个素材图层&#xff0c;右键单击并选择“场景编辑检测”。Ae菜单…

【华为OD机试真题】用 C++ 实现 - 数字加减游戏

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

从「雄狮」到「瑶光」,奇瑞历史突破背后的十字路口

传统自主品牌&#xff0c;正走到关键的十字路口。 奇瑞官方数据显示&#xff0c;2022年奇瑞集团创造了四个“历史首次”突破&#xff0c;包括年营业收入首次突破2000亿元&#xff1b;年销量首次超100万辆&#xff1b;年出口首次抵达45万辆&#xff1b;新能源年销量首次超过20万…

华为OD机试 - 组装新的数组(Python)【2023-Q1 新题】

华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 组装新的数组 题…

Linux | 网络通信 | http协议介绍 | cookie策略讲解

文章目录url统一资源定位符http协议介绍GET vs POSThttp状态码http常见headercookie session上篇博客定制了一个协议&#xff0c;该协议用来进行简单的计算&#xff0c;其包含了数据的序列化和反序列化&#xff0c;编码和解码的定制&#xff0c;并且该协议基于TCP通信&#xf…

STM32f103封装 led程序CubeMX

本文代码使用 HAL 库。 文章目录前言一、LED 原理图二、CubeMX创建工程三、LED 相关函数1. 输出电平函数&#xff1a;2. 延时函数&#xff1a;3. 翻转电平函数&#xff1a;四、详细代码实验现象 &#xff1a;总结代码 源码&#xff1a;前言 从这篇文章开始&#xff0c;我们讲解…