乘风原创程序

  • Java网络编程简单了解
  • 2021/2/23 10:39:08
  • 这篇文章将简单了解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
    CSDN

    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