在 Java 中实现 TCP 长连接有多种方式,下面我将为你详细介绍两种常见的方式:Socket 和 Netty。每种方式都将包括步骤流程和示例代码,并提供 Maven 和 Gradle 的依赖坐标。
步骤流程:
ServerSocket
监听指定端口,客户端使用 Socket
连接服务器的 IP 和端口。示例代码:
服务器端:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Server is listening...");
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected: " + clientSocket.getInetAddress());
// Handle client communication using input/output streams
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String message;
while ((message = in.readLine()) != null) {
System.out.println("Received: " + message);
out.println("Server received: " + message);
}
clientSocket.close();
}
}
}
客户端:
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 12345);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
String userInput;
while ((userInput = consoleReader.readLine()) != null) {
out.println(userInput);
String response = in.readLine();
System.out.println("Server response: " + response);
}
socket.close();
}
}
依赖坐标:
这种方式不需要任何第三方库的依赖。
步骤流程:
示例代码:
服务器端:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class Server {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new ServerHandler());
}
});
ChannelFuture future = serverBootstrap.bind(12345).sync();
System.out.println("Server is listening...");
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
服务器处理器:
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf buffer = (ByteBuf) msg;
byte[] bytes = new byte[buffer.readableBytes()];
buffer.readBytes(bytes);
String message = new String(bytes);
System.out.println("Received: " + message);
// Send response
ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("Server received: ".getBytes()).writeBytes(bytes));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
客户端:
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new ClientHandler());
}
});
Channel channel = bootstrap.connect("localhost", 12345).sync().channel();
Scanner scanner = new Scanner(System.in);
while (true) {
String userInput = scanner.nextLine();
ByteBuf messageBuffer = Unpooled.copiedBuffer(userInput.getBytes());
channel.writeAndFlush(messageBuffer);
}
} finally {
group.shutdownGracefully();
}
}
}
客户端处理器:
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class ClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf buffer = (ByteBuf) msg;
byte[] bytes = new byte[buffer.readableBytes()];
buffer.readBytes(bytes);
String response = new String(bytes);
System.out.println("Server response: " + response);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
依赖坐标:
在 Maven 中添加 Netty 的依赖:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.68.Final</version>
</dependency>
在 Gradle 中添加 Netty 的依赖:
implementation 'io.netty:netty-all:4.1.68.Final'
这些示例代码和步骤流程应该能帮助你实现 TCP 长连接,无论是使用原生 Socket 还是 Netty。注意,这些代码仅作为示例,实际项目中可能需要根据需求进行更多的细节处理和错误处理。