Java 网络编程

Java 网络编程基于 TCP/IP 协议栈,核心类位于 java.net 包中,核心是通过 Socket 抽象实现进程间通信。


一、网络编程基础原理
  1. Socket 通信模型

    • 本质:网络通信端点(IP地址 + 端口号),通过输入/输出流传输数据
    • 通信流程
      连接请求
      接受连接
      数据交换
      客户端
      服务端
      建立双向数据通道
      关闭连接
  2. TCP vs UDP 核心区别

    特性TCPUDP
    连接方式面向连接(三次握手)无连接
    可靠性可靠传输(重传机制)尽力交付(可能丢包)
    数据边界字节流(需处理粘包)数据报文(自带边界)
    适用场景文件传输、HTTP视频流、DNS查询
    Java 实现类Socket/ServerSocketDatagramSocket/DatagramPacket

二、TCP Socket 编程详解
1. 服务端实现(含多线程并发)
import java.net.*;
import java.io.*;
import java.util.concurrent.*;

public class ConcurrentServer {
    public static void main(String[] args) throws IOException {
        ExecutorService pool = Executors.newCachedThreadPool(); // 线程池
        try (ServerSocket server = new ServerSocket(8080)) {
            System.out.println("服务器启动,等待连接...");
            while (true) {
                Socket client = server.accept(); // 阻塞等待客户端
                pool.execute(() -> handleClient(client)); // 线程处理
            }
        }
    }
    
    private static void handleClient(Socket client) {
        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(client.getInputStream()));
             PrintWriter out = new PrintWriter(client.getOutputStream(), true)) {
            
            String request;
            while ((request = in.readLine()) != null) { // 持续读取
                System.out.println("客户端["+client.getPort()+"]: " + request);
                out.println("ECHO: " + request); // 回传数据
            }
        } catch (IOException e) {
            System.err.println("客户端异常断开: " + e.getMessage());
        }
    }
}
2. 客户端实现
import java.net.*;
import java.io.*;

public class AdvancedClient {
    public static void main(String[] args) throws IOException {
        try (Socket socket = new Socket("localhost", 8080);
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(
                 new InputStreamReader(socket.getInputStream()));
             BufferedReader stdIn = new BufferedReader(
                 new InputStreamReader(System.in))) {
            
            System.out.println("已连接服务器,输入消息(exit退出):");
            String userInput;
            while (!(userInput = stdIn.readLine()).equalsIgnoreCase("exit")) {
                out.println(userInput); // 发送消息
                System.out.println("服务器回复: " + in.readLine()); // 接收回复
            }
        }
    }
}

三、UDP 编程实战
1. 发送端(支持超时重传)
import java.net.*;
import java.util.concurrent.*;

public class ReliableUDPSender {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket();
        socket.setSoTimeout(3000); // 设置接收超时3秒
        
        String message = "重要数据";
        byte[] buffer = message.getBytes();
        InetAddress address = InetAddress.getByName("localhost");
        
        DatagramPacket packet = new DatagramPacket(
            buffer, buffer.length, address, 9999);
        
        // 重传机制(最多3次)
        for (int i=0; i<3; i++) {
            socket.send(packet);
            try {
                socket.receive(packet); // 等待ACK
                System.out.println("确认送达");
                break;
            } catch (SocketTimeoutException e) {
                System.out.println("超时,第"+(i+1)+"次重发...");
            }
        }
        socket.close();
    }
}
2. 接收端(含ACK响应)
import java.net.*;

public class UDPReceiverWithACK {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(9999);
        byte[] buffer = new byte[1024];
        
        while (true) {
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            socket.receive(packet); // 接收数据
            
            String data = new String(
                packet.getData(), 0, packet.getLength()
            );
            System.out.println("收到: " + data);
            
            // 发送ACK确认
            byte[] ack = "ACK".getBytes();
            DatagramPacket ackPacket = new DatagramPacket(
                ack, ack.length, packet.getAddress(), packet.getPort()
            );
            socket.send(ackPacket);
        }
    }
}

四、核心工作机制解析
  1. TCP 三次握手(连接建立)

    sequenceDiagram
    客户端->>服务端: SYN=1, seq=x
    服务端->>客户端: SYN=1, ACK=1, seq=y, ack=x+1
    客户端->>服务端: ACK=1, seq=x+1, ack=y+1
    
  2. 粘包/拆包解决方案

    • 定长协议:固定每个消息长度(如512字节)
    • 分隔符out.println(msg)自动添加\n
    • 头部长度字段
      // 发送端
      byte[] data = message.getBytes();
      out.writeInt(data.length); // 先写长度
      out.write(data);          // 再写数据
      
      // 接收端
      int length = in.readInt();
      byte[] buffer = new byte[length];
      in.readFully(buffer);    // 读满指定长度
      
  3. NIO 与传统 BIO 对比

    特性BIO (阻塞I/O)NIO (非阻塞I/O)
    线程模型1连接=1线程1线程处理多连接
    资源消耗高(线程上下文切换)低(事件驱动)
    适用场景连接数<1000高并发(如10万+连接)
    核心类ServerSocket/SocketSelector/Channel/Buffer

五、高级应用场景
  1. HTTP 客户端实现

    URL url = new URL("https://api.example.com/data");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    try (BufferedReader reader = new BufferedReader(
         new InputStreamReader(conn.getInputStream()))) {
         // 处理响应数据
    }
    
  2. WebSocket 通信(需第三方库如 Java-WebSocket

  3. RMI 远程方法调用

    // 服务端
    MyService impl = new MyServiceImpl();
    LocateRegistry.createRegistry(1099);
    Naming.rebind("rmi://localhost/MyService", impl);
    
    // 客户端
    MyService service = (MyService) Naming.lookup("rmi://localhost/MyService");
    service.doSomething();
    

六、最佳实践与调试
  1. 资源关闭规范

    try (Socket socket = new Socket(...);
         OutputStream os = socket.getOutputStream()) {
         // 使用资源
    } // 自动关闭
    
  2. 网络诊断工具

    • telnet localhost 8080 测试端口连通性
    • Wireshark 抓包分析协议细节
    • netstat -ano | findstr 8080 查看端口占用
  3. 常见异常处理

    • ConnectException:目标服务未启动
    • SocketTimeoutException:网络延迟或阻塞
    • BindException:端口被占用

网络编程的核心是理解协议栈与数据流处理,通过 Socket 抽象实现端到端通信。

思维导图

Java 网络编程

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值