Java – 网络编程


使用 Java 进行网络编程时,由虚拟机实现了底层复杂的网络协议,Java 程序只需要调用 Java 标准库提供的接口,就可以简单高效地编写网络程序。Java 提供的这些标准库存在于 java.net 包下。

TCP 编程

Socket 是一个抽象概念,一个应用程序通过一个 Socket 来建立一个远程连接,而 Socket 内部通过 TCP/IP 协议把数据传输到网络。Socket、TCP 和部分 IP 的功能都是由操作系统提供的,不同的编程语言只是提供了对操作系统调用的简单的封装。

服务端

public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        OutputStream output = null;
        try {
            serverSocket = new ServerSocket(8888);
            System.out.println("Server is running...");
            // 没连接就会阻塞
            socket = serverSocket.accept();
            output = socket.getOutputStream();
            output.write("您好,欢迎访问服务端!".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally { //由下向上,依次关闭
            if(output != null ){
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null ){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(serverSocket != null ){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

结果:Server is running…

客户端

public class Client {
    public static void main(String[] args) {
        Socket socket = null;
        InputStream input = null;
        try {
            InetAddress addressIP = InetAddress.getByName("127.0.0.1");
            int port = 8888;
            socket = new Socket(addressIP, port); //尝试建立连接
            input = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int len;
            StringBuilder sb = new StringBuilder();
            while ((len = input.read(bytes)) != -1) {
                sb.append(new String(bytes, 0, len, "UTF-8"));
            }
            System.out.println(sb);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(input != null ){
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null ){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

结果:您好,欢迎访问服务端!

UDP 编程

UDP编程就简单得多,因为UDP没有创建连接,数据包也是一次收发一个,所以没有流的概念。

服务端

public class Server {
    public static void main(String[] args) {
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(6666); // 监听指定端口
            for (;;) {
                // 数据缓冲区:
                byte[] buffer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                ds.receive(packet); // 收取一个UDP数据包
                String s = new String(packet.getData(), packet.getOffset(), packet.getLength(), StandardCharsets.UTF_8);
                System.out.println(s);
                // 发送数据:
                byte[] data = "请求已收到!".getBytes(StandardCharsets.UTF_8);
                packet.setData(data);
                ds.send(packet);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            ds.close();
        }
    }
}

结果:你好,我发了个包!

客户端

public class Client {
    public static void main(String[] args) {
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket();
            ds.setSoTimeout(1000);
            ds.connect(InetAddress.getByName("localhost"), 6666);
            // 发送:
            byte[] data = "你好,我发了个包!".getBytes();
            DatagramPacket packet = new DatagramPacket(data, data.length);
            ds.send(packet);
            // 接收:
            byte[] buffer = new byte[1024];
            packet = new DatagramPacket(buffer, buffer.length);
            ds.receive(packet);
            String resp = new String(packet.getData(), packet.getOffset(), packet.getLength());
            System.out.println(resp);
            ds.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ds.close();
        }
    }
}

结果:请求已收到!

HTTP 编程

HTTP 是 HyperText Transfer Protocol 的缩写,翻译为超文本传输协议,它是基于 TCP 协议之上的一种请求-响应协议。HTTP 请求的格式是固定的,它由 HTTP Header 和 HTTP Body 两部分构成。

服务端

服务器端的 HTTP 编程本质上就是编写 Web 服务器,这是一个非常复杂的体系,也是 JavaEE 开发的核心内容,本次就不实现了。

客户端

浏览器也是一种 HTTP 客户端,客户端的 HTTP 编程,它的行为本质上和浏览器是一样的,即发送一个 HTTP 请求,接收服务器响应后,获得响应内容。

public class Client {
    public static void main(String[] args) throws IOException {
        URL url = new URL("https://www.baidu.com/");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setUseCaches(false);
        conn.setConnectTimeout(5000); // 请求超时5秒
        // 设置HTTP头:
        conn.setRequestProperty("Accept", "*/*");
        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 11; Windows NT 5.1)");
        // 连接并发送HTTP请求:
        conn.connect();
        // 判断HTTP响应是否200:
        if (conn.getResponseCode() != 200) {
            throw new RuntimeException("bad response");
        }
        // 获取所有响应Header:
        Map<String, List<String>> map = conn.getHeaderFields();
        for (String key : map.keySet()) {
            System.out.println(key + ": " + map.get(key));
        }
        // 获取响应内容:
        InputStream input = conn.getInputStream();
    }
}

从 Java 11 开始,引入了新的 HttpClient,它使用链式调用的 API,能大大简化 HTTP 的处理。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/java/280328.html

(0)
上一篇 2022年8月13日 18:57
下一篇 2022年8月13日 19:02

相关推荐

发表回复

登录后才能评论