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

一、Socket编程基础

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

TCP Socket编程

java 复制代码
// 服务器端
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编程

java 复制代码
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

java 复制代码
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详解

java 复制代码
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模型

java 复制代码
// 传统阻塞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模型

java 复制代码
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服务器

java 复制代码
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. 资源泄露
java 复制代码
// 错误:未关闭资源
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. 超时处理
java 复制代码
// 错误:未设置超时
URLConnection conn = url.openConnection();
InputStream in = conn.getInputStream(); // 可能永远阻塞

// 正确做法
URLConnection conn = url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
  1. 并发处理
java 复制代码
// 错误:每个连接创建新线程
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));
}

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

相关推荐
qfljg2 小时前
OpenRewrite 实战指南
java
Sylvia33.2 小时前
LOL实时数据接入深度解析:从WebSocket到完整数据模型
java·网络·python·websocket·网络协议
2601_962071577 小时前
【Java报错已解决】org.springframework.beans.factory.BeanCreationException
java·开发语言
zww89491118 小时前
酒馆预约系统开发实战:从需求分析到上线全流程指南
java·eclipse
淡海水8 小时前
07-04-并发-ConcurrentBag-T-工作窃取WorkStealing算法
开发语言·算法·c#·bag·concurrent·workstealing
CS_Zero9 小时前
C语言sizeof是函数吗?
c语言·开发语言
-今昭-10 小时前
《V2V 迁移实战:将 VMware 虚拟机转为 OpenStack 可用 Glance qcow2 镜像》
开发语言·python
zww894911111 小时前
匿名树洞系统开发实战:从需求分析到部署指南
java·eclipse
黑马程序员毕设12 小时前
基于Java的医院药品管理系统的优化设计与实现
java·开发语言·spring boot·小程序·架构·课程设计·毕设
木井巳12 小时前
【BFS/DFS 解决 FloodFill 算法】太平洋大西洋水流问题
java·算法·leetcode·深度优先·广度优先·宽度优先·推荐算法