← 返回首页

Java Socket编程详解

📂 java ⏱ 4 min 603 words

Socket编程基础

Socket是网络通信的端点,Java通过Socket和ServerSocket类实现TCP通信。

TCP Socket详解

基本TCP客户端

import java.io.*;
import java.net.Socket;

public class BasicTcpClient {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 8080)) {
            socket.setSoTimeout(5000);

            OutputStream out = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(out, true);
            writer.println("Hello Server");

            InputStream in = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String response = reader.readLine();
            System.out.println("服务器响应: " + response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

基本TCP服务器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class BasicTcpServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8080)) {
            System.out.println("服务器启动,监听端口8080...");

            while (true) {
                Socket client = serverSocket.accept();
                new Thread(() -> handleClient(client)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void handleClient(Socket client) {
        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(client.getInputStream()));
             PrintWriter out = new PrintWriter(client.getOutputStream(), true)) {

            String message = in.readLine();
            System.out.println("收到: " + message);
            out.println("Echo: " + message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

多线程聊天服务器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class ChatServer {
    private static final Set<PrintWriter> clients = ConcurrentHashMap.newKeySet();

    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(9000)) {
            System.out.println("聊天服务器启动...");

            while (true) {
                Socket client = serverSocket.accept();
                new Thread(() -> handleClient(client)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void handleClient(Socket client) {
        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(client.getInputStream()));
             PrintWriter out = new PrintWriter(client.getOutputStream(), true)) {

            clients.add(out);
            String message;
            while ((message = in.readLine()) != null) {
                broadcast(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            clients.remove(client);
        }
    }

    private static void broadcast(String message) {
        for (PrintWriter client : clients) {
            client.println(message);
        }
    }
}

文件传输

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class FileTransferServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8888)) {
            System.out.println("文件传输服务器启动...");

            while (true) {
                Socket client = serverSocket.accept();
                new Thread(() -> receiveFile(client)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void receiveFile(Socket client) {
        try (DataInputStream dis = new DataInputStream(client.getInputStream())) {
            String fileName = dis.readUTF();
            long fileSize = dis.readLong();

            try (FileOutputStream fos = new FileOutputStream("received_" + fileName)) {
                byte[] buffer = new byte[4096];
                long remaining = fileSize;
                int read;

                while (remaining > 0 &&
                       (read = dis.read(buffer, 0, (int) Math.min(buffer.length, remaining))) != -1) {
                    fos.write(buffer, 0, read);
                    remaining -= read;
                }
            }
            System.out.println("文件接收完成: " + fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class FileTransferClient {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 8888);
             DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
             FileInputStream fis = new FileInputStream("test.txt")) {

            File file = new File("test.txt");
            dos.writeUTF(file.getName());
            dos.writeLong(file.length());

            byte[] buffer = new byte[4096];
            int read;
            while ((read = fis.read(buffer)) != -1) {
                dos.write(buffer, 0, read);
            }

            System.out.println("文件发送完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Socket选项

import java.net.Socket;

public class SocketOptionsDemo {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket();

        socket.setTcpNoDelay(true);
        socket.setSoTimeout(30000);
        socket.setKeepAlive(true);
        socket.setSendBufferSize(1024 * 1024);
        socket.setReceiveBufferSize(1024 * 1024);
        socket.setSoLinger(true, 30);

        System.out.println("TCP No Delay: " + socket.getTcpNoDelay());
        System.out.println("SO Timeout: " + socket.getSoTimeout());
        System.out.println("Keep Alive: " + socket.getKeepAlive());
        System.out.println("发送缓冲区: " + socket.getSendBufferSize());
        System.out.println("接收缓冲区: " + socket.getReceiveBufferSize());

        socket.close();
    }
}

NIO Socket

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class NioSocketDemo {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.bind(new InetSocketAddress(8080));
        serverChannel.configureBlocking(false);

        System.out.println("NIO服务器启动...");

        while (true) {
            SocketChannel clientChannel = serverChannel.accept();
            if (clientChannel != null) {
                clientChannel.configureBlocking(false);
                ByteBuffer buffer = ByteBuffer.allocate(1024);

                int bytesRead = clientChannel.read(buffer);
                if (bytesRead > 0) {
                    buffer.flip();
                    byte[] data = new byte[buffer.remaining()];
                    buffer.get(data);
                    System.out.println("收到: " + new String(data));

                    clientChannel.write(ByteBuffer.wrap("Echo".getBytes()));
                }

                clientChannel.close();
            }
        }
    }
}

Socket最佳实践

  1. 使用try-with-resources自动关闭Socket
  2. 设置合理的超时时间
  3. 使用多线程处理多个客户端
  4. 考虑使用NIO提高性能
  5. 注意异常处理和资源释放

总结

Socket编程是Java网络编程的核心。掌握TCP/UDP Socket的使用,能帮助你构建各种网络应用。