Java 网络编程教程_java nio网络编程
第一节:网络协议TCP/UDP/SOCKET 介绍
1.1 网络协议基础
网络协议是计算机网络中数据交换的规则和标准。Java主要支持以下协议:
TCP (Transmission Control Protocol)
- 特点:面向连接、可靠传输、字节流服务
 - 优点:数据完整性保证、顺序传输、流量控制
 - 缺点:建立连接开销大、传输效率相对较低
 - 应用场景:文件传输、邮件发送、网页浏览(HTTP)
 
UDP (User Datagram Protocol)
- 特点:无连接、不可靠传输、数据报服务
 - 优点:传输效率高、延迟低、开销小
 - 缺点:不保证数据完整性、可能丢包、无序到达
 - 应用场景:视频流、语音通话、在线游戏
 
SOCKET 套接字
- 定义:网络通信的端点,包含IP地址和端口号
 - 类型:
 - 流套接字(SOCK_STREAM):基于TCP
 - 数据报套接字(SOCK_DGRAM):基于UDP
 - 作用:应用程序通过网络进行数据交换的接口
 
1.2 SOCKET 与 TCP/UDP 的关系
1.2.1 SOCKET 是编程接口,TCP/UDP 是传输协议
关键关系:
- SOCKET 是操作系统提供的**编程接口**(API)
 - TCP/UDP 是网络传输的协议标准
 - SOCKET 封装了底层TCP/UDP协议的实现细节
 
// TCP Socket - 基于TCP协议的Socket编程
Socket tcpSocket = new Socket("localhost", 8080);
// UDP Socket - 基于UDP协议的Socket编程  
DatagramSocket udpSocket = new DatagramSocket(8080);1.2.4 协议选择对比
特性  | TCP Socket  | UDP Socket  | 
连接方式  | 面向连接  | 无连接  | 
数据传输  | 字节流  | 数据报  | 
可靠性  | 自动重传、确认机制  | 需要应用层处理  | 
顺序性  | 保证数据顺序  | 不保证顺序  | 
开销  | 较大  | 较小  | 
适用场景  | 文件传输、Web请求  | 实时音视频、游戏  | 
1.3 Java网络编程核心类
// TCP相关
ServerSocket  // 服务器端套接字
Socket        // 客户端套接字
// UDP相关
DatagramSocket      // UDP套接字
DatagramPacket     // 数据包
// 通用
InetAddress        // IP地址处理第二节:TCP Socket 示例 - 双向通信
2.1 TCP 服务器端代码
import java.io.*;
import java.net.*;
public class TCPServer {
    public static void main(String[] args) {
        final int PORT = 8888;
        
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("TCP服务器启动,等待客户端连接...");
            
            Socket clientSocket = serverSocket.accept();
            System.out.println("客户端连接成功: " + clientSocket.getInetAddress());
            
            // 接收客户端消息
            BufferedReader in = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));
            String clientMessage = in.readLine();
            System.out.println("收到客户端消息: " + clientMessage);
            
            // 发送响应
            PrintWriter out = new PrintWriter(
                clientSocket.getOutputStream(), true);
            out.println("Hello,Server");
            
            System.out.println("消息发送完成");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}2.2 TCP 客户端代码
import java.io.*;
import java.net.*;
public class TCPClient {
    public static void main(String[] args) {
        final String SERVER_IP = "localhost";
        final int PORT = 8888;
        
        try (Socket socket = new Socket(SERVER_IP, PORT)) {
            System.out.println("连接TCP服务器成功");
            
            // 发送消息
            PrintWriter out = new PrintWriter(
                socket.getOutputStream(), true);
            out.println("Hello,Client");
            
            // 接收响应
            BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
            String serverResponse = in.readLine();
            System.out.println("收到服务器响应: " + serverResponse);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}2.3 TCP 运行步骤
2.4 TCP 预期输出
服务器端输出:
TCP服务器启动,等待客户端连接...
客户端连接成功: /127.0.0.1
收到客户端消息: Hello,Client
消息发送完成客户端输出:
连接TCP服务器成功
收到服务器响应: Hello,Server第三节:UDP Socket 示例 - 数据报通信
3.1 UDP 服务器端代码
import java.net.*;
public class UDPServer {
    public static void main(String[] args) {
        final int PORT = 8888;
        
        try (DatagramSocket serverSocket = new DatagramSocket(PORT)) {
            System.out.println("UDP服务器启动,监听端口: " + PORT);
            
            byte[] receiveBuffer = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
            
            serverSocket.receive(receivePacket);
            
            String clientMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("收到客户端消息: " + clientMessage);
            System.out.println("客户端地址: " + receivePacket.getAddress().getHostAddress());
            
            String responseMessage = "hello,udp i am server";
            byte[] sendBuffer = responseMessage.getBytes();
            
            DatagramPacket sendPacket = new DatagramPacket(
                sendBuffer, 
                sendBuffer.length, 
                receivePacket.getAddress(), 
                receivePacket.getPort()
            );
            
            serverSocket.send(sendPacket);
            System.out.println("已向客户端发送响应");
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}3.2 UDP 客户端代码
import java.net.*;
public class UDPClient {
    public static void main(String[] args) {
        final String SERVER_IP = "localhost";
        final int PORT = 8888;
        
        try (DatagramSocket clientSocket = new DatagramSocket()) {
            System.out.println("UDP客户端启动");
            
            String message = "hello,udp i am client";
            byte[] sendBuffer = message.getBytes();
            
            InetAddress serverAddress = InetAddress.getByName(SERVER_IP);
            DatagramPacket sendPacket = new DatagramPacket(
                sendBuffer, 
                sendBuffer.length, 
                serverAddress, 
                PORT
            );
            
            clientSocket.send(sendPacket);
            System.out.println("已向服务器发送消息: " + message);
            
            byte[] receiveBuffer = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
            
            clientSocket.setSoTimeout(3000);
            clientSocket.receive(receivePacket);
            
            String serverResponse = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("收到服务器响应: " + serverResponse);
            
        } catch (SocketTimeoutException e) {
            System.out.println("接收超时,服务器可能未响应");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}3.4 UDP 预期输出
服务器端输出:
UDP服务器启动,监听端口: 8888
收到客户端消息: hello,udp i am client
客户端地址: 127.0.0.1
已向客户端发送响应客户端输出:
UDP客户端启动
已向服务器发送消息: hello,udp i am client
收到服务器响应: hello,udp i am server第四节:TCP vs UDP 对比总结
4.1 编程模型对比
方面  | TCP Socket  | UDP Socket  | 
连接建立  | 需要accept()和connect()  | 无连接建立过程  | 
数据传输  | 使用InputStream/OutputStream  | 使用DatagramPacket  | 
数据边界  | 字节流,无边界  | 数据报,有边界  | 
可靠性  | 自动处理重传和确认  | 需要手动处理可靠性  | 
性能  | 相对较慢  | 相对较快  | 
4.2 选择建议
选择TCP当:
- 需要可靠的数据传输
 - 数据完整性很重要
 - 传输大量数据
 - 需要维护持久连接
 
选择UDP当:
- 实时性要求高于可靠性
 - 传输小量数据
 - 需要广播或多播功能
 - 应用层自己处理可靠性
 
4.3 注意事项
- 端口冲突:TCP和UDP可以使用相同的端口号,不会冲突
 - 资源释放:确保正确关闭所有资源
 - 异常处理:网络操作必须处理IOException
 - 超时设置:合理设置连接和读取超时
 
第五节:扩展练习
5.1 多客户端TCP服务器
// 多线程TCP服务器示例
while (true) {
    Socket clientSocket = serverSocket.accept();
    new Thread(() -> {
        // 处理客户端通信
    }).start();
}5.2 UDP广播示例
// UDP广播发送
InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255");
DatagramPacket packet = new DatagramPacket(data, data.length, broadcastAddress, port);
socket.send(packet);5.3 文件传输
基于TCP Socket实现文件传输功能
第六节:常见问题解答
Q1: 为什么UDP不需要建立连接?
A: UDP是无连接协议,每个数据包都是独立的,不需要维护连接状态。
Q2: TCP和UDP可以同时使用同一个端口吗?
A: 可以,TCP和UDP的端口空间是独立的。
Q3: 如何选择TCP还是UDP?
A: 根据应用需求选择:需要可靠性选TCP,需要实时性选UDP。
Q4: 为什么UDP可能更适合实时应用?
A: UDP延迟低,没有重传机制,更适合实时音视频传输。
总结
本教程完整介绍了:
- TCP和UDP协议的基本原理和区别
 - Java中TCP和UDP Socket编程的实现
 - 完整的双向通信示例代码
 - 两种协议的适用场景和选择建议
 - 实际编程中的注意事项