rip demo
This commit is contained in:
parent
69caff37c2
commit
2d3d7d64d5
30
pom.xml
Normal file
30
pom.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>cn.x47</groupId>
|
||||
<artifactId>rip</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.1.68.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.34</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
70
src/main/java/cn/x47/RIPService.java
Normal file
70
src/main/java/cn/x47/RIPService.java
Normal file
@ -0,0 +1,70 @@
|
||||
package cn.x47;
|
||||
|
||||
|
||||
import cn.x47.config.Config;
|
||||
import cn.x47.model.RIPEntry;
|
||||
import cn.x47.model.RIPPacket;
|
||||
import cn.x47.service.RIPClient;
|
||||
import cn.x47.service.RIPServer;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class RIPService {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// 启动服务器
|
||||
RIPServer server = new RIPServer();
|
||||
new Thread(() -> {
|
||||
try {
|
||||
server.start();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
|
||||
// 启动客户端
|
||||
RIPClient client = new RIPClient();
|
||||
|
||||
// 定期发送路由更新
|
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
scheduler.scheduleAtFixedRate(() -> {
|
||||
RIPPacket packet = createRipResponsePacket(Config.RIP_VERSION);
|
||||
client.sendRipPacket(packet);
|
||||
}, 0, 30, TimeUnit.SECONDS);
|
||||
|
||||
// 主线程等待
|
||||
Thread.currentThread().join();
|
||||
}
|
||||
|
||||
private static RIPPacket createRipResponsePacket(byte version) {
|
||||
List<RIPEntry> entries = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// 示例:添加本地路由条目
|
||||
InetAddress localAddress = InetAddress.getByName("192.168.100.0");
|
||||
InetAddress subnetMask = InetAddress.getByName("255.255.255.0");
|
||||
InetAddress nextHop = InetAddress.getByName("192.168.123.45");
|
||||
|
||||
RIPEntry entry = new RIPEntry();
|
||||
entry.setAddressFamily((short) 2); // AF_INET
|
||||
entry.setIpAddress(localAddress);
|
||||
entry.setMetric(1);
|
||||
|
||||
if (version == 2) {
|
||||
entry.setRouteTag((short) 0);
|
||||
entry.setSubnetMask(subnetMask);
|
||||
entry.setNextHop(nextHop);
|
||||
}
|
||||
|
||||
entries.add(entry);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new RIPPacket((byte) 2, version, entries); // Command=2 (Response)
|
||||
}
|
||||
}
|
6
src/main/java/cn/x47/config/Config.java
Normal file
6
src/main/java/cn/x47/config/Config.java
Normal file
@ -0,0 +1,6 @@
|
||||
package cn.x47.config;
|
||||
|
||||
public class Config {
|
||||
// 设置协议版本,1 表示 RIP v1,2 表示 RIP v2
|
||||
public static final byte RIP_VERSION = 2;
|
||||
}
|
64
src/main/java/cn/x47/handle/RIPPacketDecoder.java
Normal file
64
src/main/java/cn/x47/handle/RIPPacketDecoder.java
Normal file
@ -0,0 +1,64 @@
|
||||
package cn.x47.handle;
|
||||
|
||||
|
||||
import cn.x47.model.RIPEntry;
|
||||
import cn.x47.model.RIPPacket;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 解码器
|
||||
*/
|
||||
public class RIPPacketDecoder extends MessageToMessageDecoder<DatagramPacket> {
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, DatagramPacket packet, List<Object> out) throws Exception {
|
||||
ByteBuf buf = packet.content();
|
||||
RIPPacket ripPacket = new RIPPacket();
|
||||
ripPacket.setCommand(buf.readByte());
|
||||
ripPacket.setVersion(buf.readByte());
|
||||
ripPacket.setUnused(buf.readShort());
|
||||
|
||||
List<RIPEntry> entries = new ArrayList<>();
|
||||
while (buf.readableBytes() >= 20) {
|
||||
RIPEntry entry = new RIPEntry();
|
||||
entry.setAddressFamily((short) buf.readUnsignedShort());
|
||||
|
||||
if (ripPacket.getVersion() == 2) {
|
||||
entry.setRouteTag((short) buf.readUnsignedShort());
|
||||
} else {
|
||||
entry.setRouteTag((short) 0);
|
||||
}
|
||||
|
||||
byte[] ipBytes = new byte[4];
|
||||
buf.readBytes(ipBytes);
|
||||
entry.setIpAddress(InetAddress.getByAddress(ipBytes));
|
||||
|
||||
if (ripPacket.getVersion() == 2) {
|
||||
buf.readBytes(ipBytes);
|
||||
entry.setSubnetMask(InetAddress.getByAddress(ipBytes));
|
||||
buf.readBytes(ipBytes);
|
||||
entry.setNextHop(InetAddress.getByAddress(ipBytes));
|
||||
} else {
|
||||
// 对于 RIP v1,子网掩码和下一跳需要推断或设为默认值
|
||||
entry.setSubnetMask(InetAddress.getByName("255.255.255.0")); // 示例,实际应根据 IP 类推断
|
||||
entry.setNextHop(packet.sender().getAddress());
|
||||
}
|
||||
|
||||
long metric = buf.readUnsignedInt();
|
||||
entry.setMetric(metric);
|
||||
|
||||
entries.add(entry);
|
||||
}
|
||||
ripPacket.setEntries(entries);
|
||||
ripPacket.setSenderAddress(packet.sender()); // 设置发送者地址
|
||||
out.add(ripPacket);
|
||||
}
|
||||
|
||||
}
|
53
src/main/java/cn/x47/handle/RIPPacketEncoder.java
Normal file
53
src/main/java/cn/x47/handle/RIPPacketEncoder.java
Normal file
@ -0,0 +1,53 @@
|
||||
package cn.x47.handle;
|
||||
|
||||
|
||||
import cn.x47.model.RIPEntry;
|
||||
import cn.x47.model.RIPPacket;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 编码器
|
||||
*/
|
||||
public class RIPPacketEncoder extends MessageToMessageEncoder<RIPPacket> {
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, RIPPacket msg, List<Object> out) throws Exception {
|
||||
ByteBuf buf = ctx.alloc().buffer();
|
||||
// 编码命令和版本
|
||||
buf.writeByte(msg.getCommand());
|
||||
buf.writeByte(msg.getVersion());
|
||||
buf.writeShort(msg.getUnused()); // unused 字段
|
||||
|
||||
// 编码路由条目
|
||||
for (RIPEntry entry : msg.getEntries()) {
|
||||
buf.writeShort(entry.getAddressFamily() & 0xFFFF);
|
||||
if (msg.getVersion() == 2) {
|
||||
buf.writeShort(entry.getRouteTag() & 0xFFFF);
|
||||
}
|
||||
buf.writeBytes(entry.getIpAddress().getAddress());
|
||||
|
||||
if (msg.getVersion() == 2) {
|
||||
buf.writeBytes(entry.getSubnetMask().getAddress());
|
||||
buf.writeBytes(entry.getNextHop().getAddress());
|
||||
}
|
||||
|
||||
buf.writeInt((int) entry.getMetric() & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
// 根据版本选择目标地址
|
||||
InetSocketAddress recipient;
|
||||
if (msg.getVersion() == 1) {
|
||||
recipient = new InetSocketAddress("255.255.255.255", 520);
|
||||
} else {
|
||||
recipient = new InetSocketAddress("224.0.0.9", 520);
|
||||
}
|
||||
|
||||
out.add(new DatagramPacket(buf, recipient));
|
||||
}
|
||||
|
||||
}
|
186
src/main/java/cn/x47/handle/RIPServerHandler.java
Normal file
186
src/main/java/cn/x47/handle/RIPServerHandler.java
Normal file
@ -0,0 +1,186 @@
|
||||
package cn.x47.handle;
|
||||
|
||||
import cn.x47.model.RIPEntry;
|
||||
import cn.x47.model.RIPPacket;
|
||||
import cn.x47.service.RoutingTable;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RIPServerHandler extends SimpleChannelInboundHandler<RIPPacket> {
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, RIPPacket msg) throws Exception {
|
||||
InetSocketAddress senderAddress = msg.getSenderAddress();
|
||||
byte version = msg.getVersion();
|
||||
System.out.println(msg.toString());
|
||||
|
||||
// if (msg.getCommand() == 2) { // Response
|
||||
// for (RIPEntry entry : msg.getEntries()) {
|
||||
// // 更新本地路由表
|
||||
// updateRoutingTable(entry, senderAddress, version);
|
||||
// }
|
||||
// } else if (msg.getCommand() == 1) { // Request
|
||||
// // 处理请求,发送响应包
|
||||
// handleRequest(ctx, msg);
|
||||
// }
|
||||
}
|
||||
|
||||
private void handleRequest(ChannelHandlerContext ctx, RIPPacket requestPacket) throws Exception {
|
||||
List<RIPEntry> requestEntries = requestPacket.getEntries();
|
||||
byte version = requestPacket.getVersion();
|
||||
|
||||
boolean isGeneralRequest = false;
|
||||
|
||||
// 检查是否为一般请求
|
||||
if (requestEntries.size() == 1) {
|
||||
RIPEntry entry = requestEntries.get(0);
|
||||
if (entry.getIpAddress().getHostAddress().equals("0.0.0.0") && entry.getMetric() == 16) {
|
||||
isGeneralRequest = true;
|
||||
}
|
||||
}
|
||||
|
||||
RIPPacket responsePacket = new RIPPacket();
|
||||
responsePacket.setCommand((byte) 2); // Response
|
||||
responsePacket.setVersion(version); // 与请求的版本一致
|
||||
responsePacket.setUnused((short) 0);
|
||||
List<RIPEntry> responseEntries = new ArrayList<>();
|
||||
|
||||
if (isGeneralRequest) {
|
||||
// 一般请求,返回整个路由表
|
||||
responseEntries.addAll(getAllRoutingEntries(version));
|
||||
} else {
|
||||
// 特定请求,逐一处理请求的条目
|
||||
for (RIPEntry requestEntry : requestEntries) {
|
||||
RIPEntry route = getRoutingEntry(requestEntry.getIpAddress());
|
||||
if (route != null) {
|
||||
responseEntries.add(route);
|
||||
} else {
|
||||
// 如果没有该路由,返回度量值为 16(无限)
|
||||
RIPEntry unreachableEntry = new RIPEntry();
|
||||
unreachableEntry.setAddressFamily(requestEntry.getAddressFamily());
|
||||
unreachableEntry.setIpAddress(requestEntry.getIpAddress());
|
||||
unreachableEntry.setMetric(16);
|
||||
|
||||
if (version == 2) {
|
||||
unreachableEntry.setRouteTag((short) 0);
|
||||
unreachableEntry.setSubnetMask(requestEntry.getSubnetMask());
|
||||
unreachableEntry.setNextHop(InetAddress.getByName("0.0.0.0"));
|
||||
}
|
||||
|
||||
responseEntries.add(unreachableEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 构建响应包
|
||||
responsePacket.setEntries(responseEntries);
|
||||
|
||||
// 获取发送者的地址
|
||||
InetSocketAddress recipient = requestPacket.getSenderAddress();
|
||||
|
||||
// 发送响应包
|
||||
ByteBuf buf = ctx.alloc().buffer().order(ByteOrder.BIG_ENDIAN); // 确保使用大端序
|
||||
encodeRIPPacket(responsePacket, buf);
|
||||
|
||||
DatagramPacket responseDatagram = new DatagramPacket(buf, recipient);
|
||||
ctx.writeAndFlush(responseDatagram);
|
||||
}
|
||||
|
||||
private void encodeRIPPacket(RIPPacket msg, ByteBuf buf) throws Exception {
|
||||
// 编码命令和版本
|
||||
buf.writeByte(msg.getCommand());
|
||||
buf.writeByte(msg.getVersion());
|
||||
buf.writeShort(0); // unused 字段
|
||||
|
||||
// 编码路由条目
|
||||
for (RIPEntry entry : msg.getEntries()) {
|
||||
buf.writeShort(entry.getAddressFamily());
|
||||
if (msg.getVersion() == 2) {
|
||||
buf.writeShort(entry.getRouteTag());
|
||||
}
|
||||
buf.writeBytes(entry.getIpAddress().getAddress());
|
||||
|
||||
if (msg.getVersion() == 2) {
|
||||
buf.writeBytes(entry.getSubnetMask().getAddress());
|
||||
buf.writeBytes(entry.getNextHop().getAddress());
|
||||
}
|
||||
buf.writeInt((int) (entry.getMetric() & 0xFFFFFFFFL));
|
||||
}
|
||||
}
|
||||
|
||||
private List<RIPEntry> getAllRoutingEntries(byte version) throws Exception {
|
||||
List<RIPEntry> entries = new ArrayList<>();
|
||||
// 从路由表中获取所有的路由条目
|
||||
for (RIPEntry route : RoutingTable.getInstance().getRoutes().values()) {
|
||||
RIPEntry entry = new RIPEntry();
|
||||
entry.setAddressFamily(route.getAddressFamily());
|
||||
entry.setIpAddress(route.getIpAddress());
|
||||
entry.setMetric(route.getMetric());
|
||||
|
||||
if (version == 2) {
|
||||
entry.setRouteTag(route.getRouteTag());
|
||||
entry.setSubnetMask(route.getSubnetMask());
|
||||
entry.setNextHop(route.getNextHop());
|
||||
}
|
||||
|
||||
entries.add(entry);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
private RIPEntry getRoutingEntry(InetAddress ipAddress) throws Exception {
|
||||
RIPEntry route = RoutingTable.getInstance().getRoute(ipAddress);
|
||||
if (route != null) {
|
||||
RIPEntry entry = new RIPEntry();
|
||||
entry.setAddressFamily(route.getAddressFamily());
|
||||
entry.setIpAddress(route.getIpAddress());
|
||||
entry.setMetric(route.getMetric());
|
||||
|
||||
entry.setRouteTag(route.getRouteTag());
|
||||
entry.setSubnetMask(route.getSubnetMask());
|
||||
entry.setNextHop(route.getNextHop());
|
||||
|
||||
return entry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateRoutingTable(RIPEntry entry, InetSocketAddress senderAddress, byte version) throws Exception {
|
||||
if (version == 1) {
|
||||
// 推断下一跳为发送者的地址
|
||||
entry.setNextHop(senderAddress.getAddress());
|
||||
// 根据 IP 地址类别推断子网掩码
|
||||
InetAddress ipAddress = entry.getIpAddress();
|
||||
byte[] addressBytes = ipAddress.getAddress();
|
||||
int firstOctet = addressBytes[0] & 0xFF;
|
||||
|
||||
if (firstOctet >= 0 && firstOctet <= 127) {
|
||||
// A 类地址
|
||||
entry.setSubnetMask(InetAddress.getByName("255.0.0.0"));
|
||||
} else if (firstOctet >= 128 && firstOctet <= 191) {
|
||||
// B 类地址
|
||||
entry.setSubnetMask(InetAddress.getByName("255.255.0.0"));
|
||||
} else if (firstOctet >= 192 && firstOctet <= 223) {
|
||||
// C 类地址
|
||||
entry.setSubnetMask(InetAddress.getByName("255.255.255.0"));
|
||||
} else {
|
||||
// 非法地址,忽略
|
||||
System.out.println("Invalid IP address in RIP Entry: " + ipAddress.getHostAddress());
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 实现路由表更新逻辑
|
||||
RoutingTable.getInstance().updateRoute(entry);
|
||||
System.out.println("Updated route: " + entry.getIpAddress().getHostAddress() +
|
||||
" via " + entry.getNextHop().getHostAddress() +
|
||||
" metric: " + entry.getMetric());
|
||||
}
|
||||
}
|
17
src/main/java/cn/x47/model/RIPEntry.java
Normal file
17
src/main/java/cn/x47/model/RIPEntry.java
Normal file
@ -0,0 +1,17 @@
|
||||
package cn.x47.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
@Data
|
||||
public class RIPEntry {
|
||||
private short addressFamily;
|
||||
private short routeTag; // RIP v2 特有
|
||||
private InetAddress ipAddress;
|
||||
private InetAddress subnetMask; // RIP v2 特有
|
||||
private InetAddress nextHop; // RIP v2 特有
|
||||
private long metric;
|
||||
|
||||
|
||||
}
|
28
src/main/java/cn/x47/model/RIPPacket.java
Normal file
28
src/main/java/cn/x47/model/RIPPacket.java
Normal file
@ -0,0 +1,28 @@
|
||||
package cn.x47.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RIPPacket {
|
||||
private byte command; // 1=Request, 2=Response
|
||||
private byte version; // 1=RIP v1, 2=RIP v2
|
||||
private short unused = 0; // 未使用,设置为 0
|
||||
private List<RIPEntry> entries;
|
||||
private InetSocketAddress senderAddress;
|
||||
|
||||
// 添加构造方法和 Getter/Setter
|
||||
public RIPPacket(byte command, byte version, List<RIPEntry> entries) {
|
||||
this.command = command;
|
||||
this.version = version;
|
||||
this.unused = 0;
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
}
|
47
src/main/java/cn/x47/service/RIPClient.java
Normal file
47
src/main/java/cn/x47/service/RIPClient.java
Normal file
@ -0,0 +1,47 @@
|
||||
package cn.x47.service;
|
||||
|
||||
|
||||
import cn.x47.handle.RIPPacketEncoder;
|
||||
import cn.x47.model.RIPPacket;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import io.netty.channel.socket.DatagramChannel;
|
||||
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
|
||||
|
||||
|
||||
public class RIPClient {
|
||||
|
||||
private final Bootstrap bootstrap;
|
||||
private final NioEventLoopGroup group;
|
||||
|
||||
public RIPClient() {
|
||||
group = new NioEventLoopGroup();
|
||||
bootstrap = new Bootstrap();
|
||||
bootstrap.group(group)
|
||||
.channel(NioDatagramChannel.class)
|
||||
.option(ChannelOption.SO_BROADCAST, true)
|
||||
.handler(new ChannelInitializer<DatagramChannel>() {
|
||||
@Override
|
||||
protected void initChannel(DatagramChannel ch) throws Exception {
|
||||
ch.pipeline().addLast(new RIPPacketEncoder());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void sendRipPacket(RIPPacket packet) {
|
||||
try {
|
||||
ChannelFuture future = bootstrap.bind(0).sync();
|
||||
future.channel().writeAndFlush(packet).sync();
|
||||
future.channel().close();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
34
src/main/java/cn/x47/service/RIPServer.java
Normal file
34
src/main/java/cn/x47/service/RIPServer.java
Normal file
@ -0,0 +1,34 @@
|
||||
package cn.x47.service;
|
||||
|
||||
|
||||
import cn.x47.handle.RIPPacketDecoder;
|
||||
import cn.x47.handle.RIPServerHandler;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.DatagramChannel;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
|
||||
public class RIPServer {
|
||||
|
||||
public void start() throws InterruptedException {
|
||||
NioEventLoopGroup group = new NioEventLoopGroup();
|
||||
try {
|
||||
Bootstrap b = new Bootstrap();
|
||||
b.group(group)
|
||||
.channel(NioDatagramChannel.class)
|
||||
.option(ChannelOption.SO_BROADCAST, true)
|
||||
.handler(new ChannelInitializer<DatagramChannel>() {
|
||||
@Override
|
||||
protected void initChannel(DatagramChannel ch) throws Exception {
|
||||
ch.pipeline().addLast(new RIPPacketDecoder(), new RIPServerHandler());
|
||||
}
|
||||
});
|
||||
|
||||
ChannelFuture future = b.bind(520).sync();
|
||||
future.channel().closeFuture().await();
|
||||
} finally {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
38
src/main/java/cn/x47/service/RoutingTable.java
Normal file
38
src/main/java/cn/x47/service/RoutingTable.java
Normal file
@ -0,0 +1,38 @@
|
||||
package cn.x47.service;
|
||||
|
||||
|
||||
import cn.x47.model.RIPEntry;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class RoutingTable {
|
||||
private static RoutingTable instance = new RoutingTable();
|
||||
private Map<InetAddress, RIPEntry> routes;
|
||||
|
||||
private RoutingTable() {
|
||||
routes = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public static RoutingTable getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void updateRoute(RIPEntry entry) {
|
||||
// 简单地将新路由添加或更新到路由表中
|
||||
routes.put(entry.getIpAddress(), entry);
|
||||
}
|
||||
|
||||
public void removeRoute(InetAddress ipAddress) {
|
||||
routes.remove(ipAddress);
|
||||
}
|
||||
|
||||
public Map<InetAddress, RIPEntry> getRoutes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
public RIPEntry getRoute(InetAddress ipAddress) {
|
||||
return routes.get(ipAddress);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user