【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));
}

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

相关推荐
golang学习记7 分钟前
IDEA 2026.3 远程开发迎来重磅升级
java·ide·intellij-idea·远程开发
天天被压力27 分钟前
【A股分钟级高频数据完全手册 #04】指数分钟级行情数据接口:沪深指数Pro版最新分时取数
java·人工智能·python
敲代码的小小酥30 分钟前
谈SpringMVC与Spring WebFlux的区别与适用场景
java·后端·spring
天天被压力37 分钟前
【A股分钟级高频数据完全手册 #03】股票历史1分钟K线数据接口怎么用:Pro版批量拉取与本地缓存
java·人工智能·python
zhanghaha131439 分钟前
C# 系列教程_7 判断语句(分支)保姆级精讲
开发语言·c#
apcipot_rain43 分钟前
C++转Java日记(02)
java·开发语言·c++
nice_lcj5201 小时前
【从零理解 Spring AI · 03】Spring AI 在 Spring 生态里的位置
java·spring boot·大模型·spring ai·ai应用开发
杜 硕1 小时前
从零开始的C++生活——第七讲——02
开发语言·c++·生活
zhanghaha13141 小时前
C# 系列教程_8 循环语句 保姆级精讲(面向新手)
开发语言·c#
麦麦麦当劳大王9 小时前
【油猴脚本】Boss直聘 岗位职责复制
开发语言·前端·javascript