当前位置: 首页 > article >正文

【Java入门指南 Day15:Java网络编程】

一、Socket编程基础

Socket是网络通信的基石,提供了端到端的通信机制。想象它就像电话系统,两端通过Socket建立连接后就可以互相通信。

TCP Socket编程

// 服务器端
public class SimpleServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8080)) {
            System.out.println("服务器启动,等待连接...");
            
            while (true) {
                Socket clientSocket = serverSocket.accept();
                handleClient(clientSocket);
            }
        }
    }
    
    private static void handleClient(Socket socket) {
        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
             PrintWriter out = new PrintWriter(
                socket.getOutputStream(), true)) {
            
            String line;
            while ((line = in.readLine()) != null) {
                System.out.println("收到消息: " + line);
                out.println("服务器已收到: " + line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 客户端
public class SimpleClient {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 8080);
             PrintWriter out = new PrintWriter(
                socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()))) {
            
            out.println("Hello, Server!");
            System.out.println("服务器响应: " + in.readLine());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

UDP Socket编程

public class UDPExample {
    public static void main(String[] args) throws IOException {
        // UDP服务器
        DatagramSocket serverSocket = new DatagramSocket(9000);
        byte[] receiveData = new byte[1024];
        
        while (true) {
            DatagramPacket receivePacket = 
                new DatagramPacket(receiveData, receiveData.length);
            serverSocket.receive(receivePacket);
            
            String message = new String(
                receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("收到消息: " + message);
        }
    }
}

二、HTTP客户端实现

使用HttpURLConnection

public class HttpClientExample {
    public String sendGet(String url) throws IOException {
        HttpURLConnection connection = (HttpURLConnection) 
            new URL(url).openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(connection.getInputStream()))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return response.toString();
        } finally {
            connection.disconnect();
        }
    }
    
    public String sendPost(String url, String body) throws IOException {
        HttpURLConnection connection = (HttpURLConnection) 
            new URL(url).openConnection();
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        connection.setRequestProperty("Content-Type", "application/json");
        
        try (OutputStream os = connection.getOutputStream()) {
            os.write(body.getBytes());
        }
        
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(connection.getInputStream()))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return response.toString();
        }
    }
}

三、URL和URLConnection详解

public class URLExample {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://api.example.com/data?id=123");
        
        System.out.println("协议: " + url.getProtocol());
        System.out.println("主机: " + url.getHost());
        System.out.println("端口: " + url.getPort());
        System.out.println("路径: " + url.getPath());
        System.out.println("查询参数: " + url.getQuery());
        
        URLConnection connection = url.openConnection();
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        
        // 设置请求属性
        connection.setRequestProperty("User-Agent", "Mozilla/5.0");
        
        // 获取响应头
        for (Map.Entry<String, List<String>> header : 
             connection.getHeaderFields().entrySet()) {
            System.out.println(header.getKey() + ": " + header.getValue());
        }
    }
}

四、网络IO模型

1. 阻塞IO模型

// 传统阻塞IO
ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept(); // 阻塞直到连接建立
InputStream in = socket.getInputStream();
byte[] buffer = new byte[1024];
int read = in.read(buffer); // 阻塞直到有数据可读

2. 非阻塞IO模型

public class NonBlockingServer {
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.bind(new InetSocketAddress(8080));
        serverChannel.configureBlocking(false);
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        
        while (true) {
            selector.select();
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> iter = selectedKeys.iterator();
            
            while (iter.hasNext()) {
                SelectionKey key = iter.next();
                if (key.isAcceptable()) {
                    handleAccept(serverChannel, selector);
                } else if (key.isReadable()) {
                    handleRead(key);
                }
                iter.remove();
            }
        }
    }
}

五、实用案例:简单的HTTP服务器

public class SimpleHttpServer {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8080);
        System.out.println("HTTP服务器启动,监听端口8080...");
        
        while (true) {
            Socket clientSocket = server.accept();
            new Thread(() -> handleRequest(clientSocket)).start();
        }
    }
    
    private static void handleRequest(Socket socket) {
        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
            
            // 读取HTTP请求
            String requestLine = in.readLine();
            System.out.println("收到请求: " + requestLine);
            
            // 发送HTTP响应
            out.println("HTTP/1.1 200 OK");
            out.println("Content-Type: text/html; charset=utf-8");
            out.println();
            out.println("<html><body><h1>Hello, World!</h1></body></html>");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

最佳实践建议 💡

  1. 连接管理
    • 使用连接池管理连接
    • 设置合适的超时时间
    • 正确关闭资源
  2. 错误处理
    • 实现重试机制
    • 记录详细的错误日志
  3. 性能优化
    • 使用非阻塞IO处理高并发
    • 实现数据压缩
    • 使用缓冲区提高效率

常见陷阱提醒 ⚠️

  1. 资源泄露
// 错误:未关闭资源
Socket socket = new Socket("localhost", 8080);
socket.getOutputStream().write(data);
// 应该使用try-with-resources

// 正确做法
try (Socket socket = new Socket("localhost", 8080)) {
    socket.getOutputStream().write(data);
}
  1. 超时处理
// 错误:未设置超时
URLConnection conn = url.openConnection();
InputStream in = conn.getInputStream(); // 可能永远阻塞

// 正确做法
URLConnection conn = url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
  1. 并发处理
// 错误:每个连接创建新线程
while (true) {
    Socket socket = serverSocket.accept();
    new Thread(() -> handleRequest(socket)).start();
}

// 正确:使用线程池
ExecutorService executor = Executors.newFixedThreadPool(10);
while (true) {
    Socket socket = serverSocket.accept();
    executor.submit(() -> handleRequest(socket));
}

网络编程是现代应用程序的重要组成部分。掌握这些基础知识对于构建可靠的网络应用至关重要。记住要注意资源管理、错误处理和性能优化。


http://www.kler.cn/a/442852.html

相关文章:

  • Java聊天小程序
  • Observability:将 OpenTelemetry 添加到你的 Flask 应用程序
  • Maven核心插件之maven-resources-plugin
  • neo4j 安装 (提供镜像下载方式
  • [免费]微信小程序(高校就业)招聘系统(Springboot后端+Vue管理端)【论文+源码+SQL脚本】
  • 【AniGS】论文阅读
  • C# 如何使用多线程
  • 深入理解数据库 JOIN 操作
  • 【Tomcat】第一站:理解tomcat与Socket
  • 【面试问题】JIT 是什么?和 JVM 什么关系?
  • IDEA下加载音频文件操作
  • Linux 查看文件末尾命令 tail 详细介绍
  • [LeetCode-Python版] 876. 链表的中间结点
  • 一键学懂BurpSuite(8)
  • 【Java入门指南 Day11:Lambda表达式与Stream API】
  • 8.2 分库分表简介
  • Java创建对象有几种方式?
  • 理解并使用 sysdig
  • ubuntu监测硬盘状态
  • 图像分割数据集石头rock分割数据集labelme格式2602张3类别
  • Leetcode 208实现Trie树前缀
  • iOS 核心动画
  • 【深入理解ApacheTomcat】
  • 数据结构和算法-06线段树-01
  • DOA估计算法——ESPRIT算法
  • mysql,创建数据库和用户授权核心语句