这篇文章将简单了解Java的HttpURLConnection,InetAddress,Socket以及ServerSocket

HttpURLConnection

HttpURLConnection 位于 java.net 包中,提供了用来URL连接请求的方法

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/** * @author AhogeK ahogek@gmail.com * @date 2021-02-23 16:40 */
public class HttpUrlConnectionTest { 

    public static void main(String[] args) { 
        try { 
            // 设置一个URL
            URL csdn = new URL("https://www.csdn.net/");
            // 通过设置的URL创建一个HttpURLConnection连接,URL.openConnection()返回的是URLConnection, HttpURLConnection是其子类
            HttpURLConnection httpUrlConnection = (HttpURLConnection) csdn.openConnection();
            // 设置请求的方法,类似还有很多请求配置常用的连接超时等
            httpUrlConnection.setRequestMethod("GET");
            httpUrlConnection.setConnectTimeout(1000);
            // 通过BufferedReader接收响应
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpUrlConnection.getInputStream()));
            // 输出响应内容
            bufferedReader.lines().forEach(System.out::println);
            // 关闭连接与流
            httpUrlConnection.disconnect();
            bufferedReader.close();
        } catch (Exception e) { 
            e.printStackTrace();
        }
    }
}

请求成功就能拿到CSDN的首页页面的HTML

InetAddress

该类同样在 java.net 包中,用于表示IP地址,例如在socket编程中会用到该类

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

/** * @author AhogeK ahogek@gmail.com * @date 2021-02-23 19:51 */
public class InetAddressTest { 

    public static void main(String[] args) throws UnknownHostException { 
        /* * InetAddress没有公共构造方法,我们可以通过静态方法来构建 * getByName() 方法可以通过给定主机域名来获取 InetAddress实例 */
        InetAddress google = InetAddress.getByName("www.google.com");
        // 通过 toString() 可以以 域名/IP 的格式输出
        System.out.println(google.toString());
        // getHostAddress() 用来获取InetAddress对象的IP地址
        System.out.println(google.getHostAddress());
        // getHostName() 即获取其域名
        System.out.println(google.getHostName());
        // 同理也可以反向生成实例对象
        System.out.println(InetAddress.getByAddress("www.google.com",new byte[] { (byte) 172, (byte) 217, 31, (byte) 132}).toString());
        // 输出 本地主机 地址 pc名/本地ip
        System.out.println(InetAddress.getLocalHost());
        // 因为一个域名不一定只映射一个ip,所以 getAllByName 可以获取域名相关连的多个IP
        System.out.println(Arrays.toString(InetAddress.getAllByName("www.google.com")));
    }
}

输出:

Socket与ServerSocket

Socket

同样位于 java.net,称之为套接字,是作为两台计算机相连的端点

在接下来要写的小demo中,Socket的主要步骤:

  1. 建立与服务器的连接
  2. 使用输出流将数据发送到SockerServer
  3. 使用输入流读取SocketServer返回的数据
  4. 关闭连接

ServerSocket

ServerSocket 是服务端套接字,它会等待Socket的接入,然后执行一系列操作再返回

ServerSocket的主要步骤:

  1. 创建服务器的套接字并将其绑定到特定的接口
  2. 等待客户端Socket的接入
  3. 通过接入的Socket获取其输入流读取数据
  4. 通过接入的Socket获取输出流来写入数据

DEMO

Socket

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.time.LocalDateTime;
import java.util.Scanner;

/** * @author AhogeK ahogek@gmail.com * @date 2021-02-23 21:01 */
public class SocketClient { 

    public static void main(String[] args) throws IOException { 
        System.out.println("Client start!");
        // 创建本地的InetAddress实例 (即用来获取本地服务端IP)
        InetAddress localHost = InetAddress.getLocalHost();
        // 设置服务端端口
        int port = 8080;
        // 用于进行客户端输入的操作
        Scanner clientScanner = new Scanner(System.in);
        // 通过服务器的IP与端口实例化 Socket
        Socket socket = new Socket(localHost.getHostAddress(), port);
        // 实例化 Socket 的输出流 (第二参数指是否自动flush) 用于向服务端写数据
        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
        // 实例化 Socket 的输入流 用于读取服务端数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        LocalDateTime localDateTime = LocalDateTime.now();
        // 除非输入 “exit” 不然不会关闭可以持续输出
        String clientInput;
        while (!"exit".equals(clientInput = clientScanner.nextLine())) { 
            // 客户端输入发送至服务器
            writer.println(LocalDateTime.now().toString() + " " + clientInput);
            // 输出服务端返回
            System.out.println("Server: " + br.readLine());
        }
        // 关闭 Socket
        socket.close();
    }
}

ServerSocket

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/** * @author AhogeK ahogek@gmail.com * @date 2021-02-23 21:15 */
public class ServerSocketTest { 

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;
    private static final Long KEEP_ALIVE_TIME = 1L;
    private final static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(QUEUE_CAPACITY),
            new ThreadPoolExecutor.CallerRunsPolicy());

    public static void main(String[] args) throws IOException { 
        System.out.println("Server start!");
        // 创建ServerSocket实例
        ServerSocket serverSocket = new ServerSocket(8080);
        // 使用到了Java8的流操作因此这边需要用到原子类
        AtomicBoolean close = new AtomicBoolean(false);
        // 利用这条线程来随时关闭服务器
        EXECUTOR.execute(() -> { 
            Scanner scanner = new Scanner(System.in);
           while (!"exit".equals(scanner.nextLine())) { 
               close.set(true);
           }
        });
        while (!close.get()) { 
            // 支持多线程接入Socket
            EXECUTOR.execute(() -> { 
                try { 
                    // 调用 accept() 进行阻塞等待 Socket 接入
                    Socket socket = serverSocket.accept();
                    // 接入后获取其输入输出流用于读取写入
                    PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String clientInput;
                    while ((clientInput = reader.readLine()) != null) { 
                        System.out.println("client: " + clientInput);
                        // 发回消息给客户端
                        writer.println("This is Server");
                    }
                } catch (IOException e) { 
                    e.printStackTrace();
                }
            });
        }
    }
}

输出:

上述代码中,ServerSocket 用了阿里规范中推荐的线程池ThreadPoolExecutor来创建Socket客户端接入的线程

本文地址:https://blog.csdn.net/AhogeK/article/details/113995035