Compare commits
	
		
			7 Commits
		
	
	
		
			main
			...
			497f55c40c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						497f55c40c
	
				 | 
					
					
						|||
| 
						
						
							
						
						638507e0f3
	
				 | 
					
					
						|||
| 
						
						
							
						
						a9afea0603
	
				 | 
					
					
						|||
| 
						
						
							
						
						6203c43ebe
	
				 | 
					
					
						|||
| 
						
						
							
						
						f379b02e61
	
				 | 
					
					
						|||
| 
						
						
							
						
						9eb82869f2
	
				 | 
					
					
						|||
| 
						
						
							
						
						807df279e9
	
				 | 
					
					
						
							
								
								
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							@@ -18,7 +18,7 @@
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>io.netty</groupId>
 | 
			
		||||
            <artifactId>netty-all</artifactId>
 | 
			
		||||
            <version>4.1.68.Final</version>
 | 
			
		||||
            <version>4.1.110.Final</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.projectlombok</groupId>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,12 +10,15 @@ import cn.x47.service.RIPServer;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.concurrent.*;
 | 
			
		||||
import java.util.concurrent.Executors;
 | 
			
		||||
import java.util.concurrent.ScheduledExecutorService;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
 | 
			
		||||
public class RIPService {
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) throws Exception {
 | 
			
		||||
        // 启动服务器
 | 
			
		||||
        if (Config.startServer) {
 | 
			
		||||
            RIPServer server = new RIPServer();
 | 
			
		||||
            new Thread(() -> {
 | 
			
		||||
                try {
 | 
			
		||||
@@ -24,18 +27,23 @@ public class RIPService {
 | 
			
		||||
                    e.printStackTrace();
 | 
			
		||||
                }
 | 
			
		||||
            }).start();
 | 
			
		||||
            System.out.println("服务端已经启动");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (Config.startClient) {
 | 
			
		||||
            // 启动客户端
 | 
			
		||||
            RIPClient client = new RIPClient();
 | 
			
		||||
 | 
			
		||||
            // 定期发送路由更新
 | 
			
		||||
            ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 | 
			
		||||
            scheduler.scheduleAtFixedRate(() -> {
 | 
			
		||||
                RIPPacket packet = createRipResponsePacket(Config.RIP_VERSION);
 | 
			
		||||
                client.sendRipPacket(packet);
 | 
			
		||||
        }, 0, 30, TimeUnit.SECONDS);
 | 
			
		||||
                System.out.println("客户端 发送了一次消息");
 | 
			
		||||
            }, 0, 10, TimeUnit.SECONDS);
 | 
			
		||||
            System.out.println("客户端已经启动");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//         主线程等待
 | 
			
		||||
        // 主线程等待
 | 
			
		||||
        Thread.currentThread().join();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -44,9 +52,9 @@ public class RIPService {
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // 示例:添加本地路由条目
 | 
			
		||||
            InetAddress localAddress = InetAddress.getByName("192.168.100.0");
 | 
			
		||||
            InetAddress localAddress = InetAddress.getByName("10.47.54.0");
 | 
			
		||||
            InetAddress subnetMask = InetAddress.getByName("255.255.255.0");
 | 
			
		||||
            InetAddress nextHop = InetAddress.getByName("192.168.123.45");
 | 
			
		||||
            InetAddress nextHop = InetAddress.getByName("0.0.0.0");
 | 
			
		||||
 | 
			
		||||
            RIPEntry entry = new RIPEntry();
 | 
			
		||||
            entry.setAddressFamily((short) 2); // AF_INET
 | 
			
		||||
 
 | 
			
		||||
@@ -2,5 +2,7 @@ package cn.x47.config;
 | 
			
		||||
 | 
			
		||||
public class Config {
 | 
			
		||||
    // 设置协议版本,1 表示 RIP v1,2 表示 RIP v2
 | 
			
		||||
    public static final byte RIP_VERSION = 2;
 | 
			
		||||
    public static final byte RIP_VERSION = 1;
 | 
			
		||||
    public static final boolean startServer = true;
 | 
			
		||||
    public static final boolean startClient = false;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,37 +28,26 @@ public class RIPPacketDecoder extends MessageToMessageDecoder<DatagramPacket> {
 | 
			
		||||
        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);
 | 
			
		||||
            }
 | 
			
		||||
            entry.setAddressFamily(buf.readShort());
 | 
			
		||||
            entry.setRouteTag(buf.readShort());
 | 
			
		||||
 | 
			
		||||
            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 {
 | 
			
		||||
            if (ripPacket.getVersion() == 1) {
 | 
			
		||||
                // 对于 RIP v1,子网掩码和下一跳需要推断或设为默认值
 | 
			
		||||
                entry.setSubnetMask(InetAddress.getByName("255.255.255.0")); // 示例,实际应根据 IP 类推断
 | 
			
		||||
                entry.setNextHop(packet.sender().getAddress());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            long metric = buf.readUnsignedInt();
 | 
			
		||||
            entry.setMetric(metric);
 | 
			
		||||
 | 
			
		||||
            entry.setMetric((int) buf.readUnsignedInt());
 | 
			
		||||
            entries.add(entry);
 | 
			
		||||
        }
 | 
			
		||||
        ripPacket.setEntries(entries);
 | 
			
		||||
        ripPacket.setSenderAddress(packet.sender()); // 设置发送者地址
 | 
			
		||||
        out.add(ripPacket);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,18 +25,21 @@ public class RIPPacketEncoder extends MessageToMessageEncoder<RIPPacket> {
 | 
			
		||||
 | 
			
		||||
        // 编码路由条目
 | 
			
		||||
        for (RIPEntry entry : msg.getEntries()) {
 | 
			
		||||
            buf.writeShort(entry.getAddressFamily() & 0xFFFF);
 | 
			
		||||
            buf.writeShort(entry.getAddressFamily());
 | 
			
		||||
            if (msg.getVersion() == 2) {
 | 
			
		||||
                buf.writeShort(entry.getRouteTag() & 0xFFFF);
 | 
			
		||||
                buf.writeShort(entry.getRouteTag());
 | 
			
		||||
            } else if (msg.getVersion() == 1) {
 | 
			
		||||
                buf.writeShort(0);
 | 
			
		||||
            }
 | 
			
		||||
            buf.writeBytes(entry.getIpAddress().getAddress());
 | 
			
		||||
 | 
			
		||||
            if (msg.getVersion() == 2) {
 | 
			
		||||
                buf.writeBytes(entry.getSubnetMask().getAddress());
 | 
			
		||||
                buf.writeBytes(entry.getNextHop().getAddress());
 | 
			
		||||
            } else if (msg.getVersion() == 1) {
 | 
			
		||||
                buf.writeInt(0);
 | 
			
		||||
                buf.writeInt(0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            buf.writeInt((int) entry.getMetric() & 0xFFFFFFFF);
 | 
			
		||||
            buf.writeInt(entry.getMetric());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 根据版本选择目标地址
 | 
			
		||||
@@ -49,5 +52,4 @@ public class RIPPacketEncoder extends MessageToMessageEncoder<RIPPacket> {
 | 
			
		||||
 | 
			
		||||
        out.add(new DatagramPacket(buf, recipient));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,186 +1,35 @@
 | 
			
		||||
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 字段
 | 
			
		||||
 | 
			
		||||
        // 编码路由条目
 | 
			
		||||
        System.out.println(msg);
 | 
			
		||||
        if (msg.getCommand() == 2) { // Response
 | 
			
		||||
            for (RIPEntry entry : msg.getEntries()) {
 | 
			
		||||
            buf.writeShort(entry.getAddressFamily());
 | 
			
		||||
            if (msg.getVersion() == 2) {
 | 
			
		||||
                buf.writeShort(entry.getRouteTag());
 | 
			
		||||
                // 更新本地路由表
 | 
			
		||||
                updateRoutingTable(entry);
 | 
			
		||||
            }
 | 
			
		||||
            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));
 | 
			
		||||
        } else if (msg.getCommand() == 1) { // Request
 | 
			
		||||
            // 处理请求,可能需要发送响应包
 | 
			
		||||
            // ...
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    private void updateRoutingTable(RIPEntry entry) {
 | 
			
		||||
        // 实现路由表更新逻辑
 | 
			
		||||
        // 这里只是示例,实际需要处理路由添加、更新、超时等逻辑
 | 
			
		||||
        RoutingTable.getInstance().updateRoute(entry);
 | 
			
		||||
        System.out.println("Updated route: " + entry.getIpAddress().getHostAddress() +
 | 
			
		||||
                " via " + entry.getNextHop().getHostAddress() +
 | 
			
		||||
                " metric: " + entry.getMetric());
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,13 @@ 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;
 | 
			
		||||
    private int metric;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
 | 
			
		||||
import java.net.InetSocketAddress;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@@ -15,7 +14,6 @@ public class RIPPacket {
 | 
			
		||||
    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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,12 +4,12 @@ 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.ChannelFuture;
 | 
			
		||||
import io.netty.channel.ChannelInitializer;
 | 
			
		||||
import io.netty.channel.ChannelOption;
 | 
			
		||||
import io.netty.channel.nio.NioEventLoopGroup;
 | 
			
		||||
 | 
			
		||||
import io.netty.channel.socket.DatagramChannel;
 | 
			
		||||
import io.netty.channel.socket.nio.NioDatagramChannel;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class RIPClient {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,9 @@ 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.ChannelFuture;
 | 
			
		||||
import io.netty.channel.ChannelInitializer;
 | 
			
		||||
import io.netty.channel.ChannelOption;
 | 
			
		||||
import io.netty.channel.nio.NioEventLoopGroup;
 | 
			
		||||
import io.netty.channel.socket.DatagramChannel;
 | 
			
		||||
import io.netty.channel.socket.nio.NioDatagramChannel;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package cn.x47.service;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import cn.x47.model.RIPEntry;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
@@ -31,8 +32,4 @@ public class RoutingTable {
 | 
			
		||||
    public Map<InetAddress, RIPEntry> getRoutes() {
 | 
			
		||||
        return routes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RIPEntry getRoute(InetAddress ipAddress) {
 | 
			
		||||
        return routes.get(ipAddress);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										285
									
								
								src/test/java/Connection.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								src/test/java/Connection.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,285 @@
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.ObjectInputStream;
 | 
			
		||||
import java.io.ObjectOutputStream;
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.ServerSocket;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Connection class takes input from the user
 | 
			
		||||
 * and creates threads for the client and server
 | 
			
		||||
 *
 | 
			
		||||
 * @author Ankit
 | 
			
		||||
 */
 | 
			
		||||
public class Connection {
 | 
			
		||||
 | 
			
		||||
    // Stores destination and cost to reach
 | 
			
		||||
    public static HashMap<String, Integer> table;
 | 
			
		||||
    // Stores local ip address
 | 
			
		||||
    static String[] localIP;
 | 
			
		||||
    // Stores it's neighbors
 | 
			
		||||
    static ArrayList<String> neighbors;
 | 
			
		||||
    //Stores destination and next hop
 | 
			
		||||
    public static HashMap<String, String> hop;
 | 
			
		||||
    // Subnet mask
 | 
			
		||||
    public static String subnetMask = "255.255.255.0";
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) throws IOException {
 | 
			
		||||
        table = new HashMap<>();
 | 
			
		||||
        hop = new HashMap<>();
 | 
			
		||||
        neighbors = new ArrayList<>();
 | 
			
		||||
        System.out.println(InetAddress.getLocalHost() + " connection started");
 | 
			
		||||
        localIP = InetAddress.getLocalHost().toString().split("/");
 | 
			
		||||
        System.out.println("Updated position 1");
 | 
			
		||||
        table.put(localIP[1], 0);
 | 
			
		||||
        hop.put(localIP[1], localIP[1]);
 | 
			
		||||
        // Starts the server
 | 
			
		||||
        Server server = new Server();
 | 
			
		||||
        server.start();
 | 
			
		||||
 | 
			
		||||
        int length = args.length;
 | 
			
		||||
        // User input for the neighbor ip and cost
 | 
			
		||||
        Scanner scan = new Scanner(System.in);
 | 
			
		||||
        for (int i = 0; i < length; i++) {
 | 
			
		||||
            System.out.println("Enter the cost for " + args[i].toString());
 | 
			
		||||
            int cost = scan.nextInt();
 | 
			
		||||
            new Client(args[i], cost).start();
 | 
			
		||||
        }
 | 
			
		||||
        scan.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the destination cost and the next hop
 | 
			
		||||
     *
 | 
			
		||||
     * @param temp     - routing table of neighbor
 | 
			
		||||
     * @param senderIP - sender ip address
 | 
			
		||||
     * @param tempHop  - Next hops of the sender
 | 
			
		||||
     */
 | 
			
		||||
    public static void updateTable(Map<String, Integer> temp, String senderIP, Map<String, String> tempHop) {
 | 
			
		||||
        // updates the table if neighbor has smaller value
 | 
			
		||||
        if (table.containsKey(senderIP) && temp.containsKey(localIP[1])) {
 | 
			
		||||
            if (table.get(senderIP) > temp.get(localIP[1])) {
 | 
			
		||||
                table.put(senderIP, temp.get(localIP[1]));
 | 
			
		||||
                if (tempHop.get(localIP[1]).equals(localIP[1])) {
 | 
			
		||||
                    hop.put(senderIP, senderIP);
 | 
			
		||||
                } else {
 | 
			
		||||
                    for (int i = 0; i < neighbors.size(); i++) {
 | 
			
		||||
                        if (!neighbors.get(i).equals(senderIP)) {
 | 
			
		||||
                            hop.put(senderIP, neighbors.get(i));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add the neighbor if neighbor has its entry
 | 
			
		||||
        if (!table.containsKey(senderIP)) {
 | 
			
		||||
            table.put(senderIP, temp.get(localIP[1]));
 | 
			
		||||
            hop.put(senderIP, senderIP);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SuppressWarnings("rawtypes")
 | 
			
		||||
        Iterator it = temp.entrySet().iterator();
 | 
			
		||||
        while (it.hasNext()) {
 | 
			
		||||
            @SuppressWarnings("rawtypes")
 | 
			
		||||
            Map.Entry pair = (Map.Entry) it.next();
 | 
			
		||||
            String ip = pair.getKey().toString();
 | 
			
		||||
            if (!table.containsKey(ip)) {
 | 
			
		||||
                table.put(ip, Integer.parseInt(pair.getValue().toString())
 | 
			
		||||
                        + table.get(senderIP));
 | 
			
		||||
                hop.put(ip, senderIP);
 | 
			
		||||
            } else {
 | 
			
		||||
                if (table.get(ip) > (Integer.parseInt(pair.getValue()
 | 
			
		||||
                        .toString()) + table.get(senderIP))) {
 | 
			
		||||
                    table.put(
 | 
			
		||||
                            ip,
 | 
			
		||||
                            (Integer.parseInt(pair.getValue().toString()) + table
 | 
			
		||||
                                    .get(senderIP)));
 | 
			
		||||
                    hop.put(ip, senderIP);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays the desired output i.e.
 | 
			
		||||
     * Destination, subnet mask, cost and next hop
 | 
			
		||||
     */
 | 
			
		||||
    public static void display() {
 | 
			
		||||
        @SuppressWarnings("rawtypes")
 | 
			
		||||
        Iterator it = table.entrySet().iterator();
 | 
			
		||||
        System.out.println("------ UPDATED TABLE -----");
 | 
			
		||||
        System.out.println("Destination" + '\t' + "Subnet Mask" + '\t' + "Cost" + '\t' + "Next Hop");
 | 
			
		||||
        while (it.hasNext()) {
 | 
			
		||||
            @SuppressWarnings("rawtypes")
 | 
			
		||||
            Map.Entry pair = (Map.Entry) it.next();
 | 
			
		||||
            String[] ipSubParts = pair.getKey().toString().split("\\.");
 | 
			
		||||
            String[] subnetSubParts = subnetMask.split("\\.");
 | 
			
		||||
            String[] netID = new String[4];
 | 
			
		||||
            for (int i = 0; i < ipSubParts.length; i++) {
 | 
			
		||||
                netID[i] = Integer.toString((Integer.parseInt(ipSubParts[i]) & Integer.parseInt(subnetSubParts[i])));
 | 
			
		||||
            }
 | 
			
		||||
            String networkID = netID[0] + "." + netID[1] + "." + netID[2] + "." + netID[3];
 | 
			
		||||
            // Desired output displayed
 | 
			
		||||
            System.out.println(networkID + '\t' + subnetMask + '\t' + pair.getValue() + '\t' + hop.get(pair.getKey().toString()));
 | 
			
		||||
        }
 | 
			
		||||
        System.out.println();
 | 
			
		||||
        System.out.println("----------------------------------------------");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Server class accepts the connection from the neighbors
 | 
			
		||||
 * It waits for neighbors input, updates table
 | 
			
		||||
 * and sends updated table
 | 
			
		||||
 *
 | 
			
		||||
 * @author Ankit
 | 
			
		||||
 */
 | 
			
		||||
class Server extends Thread {
 | 
			
		||||
 | 
			
		||||
    private static ServerSocket server;
 | 
			
		||||
    private Socket connection;
 | 
			
		||||
    ObjectInputStream input;
 | 
			
		||||
    ObjectOutputStream output;
 | 
			
		||||
 | 
			
		||||
    public Server() throws IOException {
 | 
			
		||||
        server = new ServerSocket(6969);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void run() {
 | 
			
		||||
        try {
 | 
			
		||||
            accept();
 | 
			
		||||
        } catch (UnknownHostException | ClassNotFoundException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void accept() throws UnknownHostException, ClassNotFoundException {
 | 
			
		||||
        try {
 | 
			
		||||
            int count = 0;
 | 
			
		||||
            while (count < 2) {
 | 
			
		||||
                count++;
 | 
			
		||||
                System.out.println(InetAddress.getLocalHost()
 | 
			
		||||
                        + " is waiting for connection " + count);
 | 
			
		||||
                // accepts the connection from the neighbors
 | 
			
		||||
                connection = server.accept();
 | 
			
		||||
                System.out.println(InetAddress.getLocalHost()
 | 
			
		||||
                        + " connected to " + connection.getInetAddress());
 | 
			
		||||
                String[] connectionIP = connection.getInetAddress().toString()
 | 
			
		||||
                        .split("/");
 | 
			
		||||
                Connection.neighbors.add(connectionIP[1]);
 | 
			
		||||
                output = new ObjectOutputStream(connection.getOutputStream());
 | 
			
		||||
                input = new ObjectInputStream(connection.getInputStream());
 | 
			
		||||
 | 
			
		||||
                // Creates new thread to interact with the client
 | 
			
		||||
                new Thread(new Runnable() {
 | 
			
		||||
                    @SuppressWarnings({"rawtypes", "unchecked"})
 | 
			
		||||
                    @Override
 | 
			
		||||
                    public void run() {
 | 
			
		||||
                        while (true) {
 | 
			
		||||
                            try {
 | 
			
		||||
                                HashMap<HashMap<String, Integer>, HashMap<String, String>> receiver;
 | 
			
		||||
                                // reads the input from the neighbor
 | 
			
		||||
                                receiver = (HashMap<HashMap<String, Integer>, HashMap<String, String>>) input.readObject();
 | 
			
		||||
                                HashMap<String, Integer> temp = (HashMap<String, Integer>) receiver.keySet().toArray()[0];
 | 
			
		||||
                                HashMap<String, String> tempHop = receiver.get(temp);
 | 
			
		||||
                                @SuppressWarnings("unused")
 | 
			
		||||
                                Iterator it = temp.entrySet().iterator();
 | 
			
		||||
                                Connection.updateTable(temp, connectionIP[1], tempHop);
 | 
			
		||||
                                HashMap<HashMap<String, Integer>, HashMap<String, String>> sender;
 | 
			
		||||
                                sender = new HashMap<HashMap<String, Integer>, HashMap<String, String>>();
 | 
			
		||||
                                sender.put(Connection.table, Connection.hop);
 | 
			
		||||
                                // sends the updated table to its neighbors
 | 
			
		||||
                                output.writeObject(sender);
 | 
			
		||||
                                output.reset();
 | 
			
		||||
                                Connection.display();
 | 
			
		||||
                                Thread.sleep(1000);
 | 
			
		||||
                            } catch (Exception e) {
 | 
			
		||||
                                System.exit(0);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }).start();
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            System.exit(0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Client asks for the connection to the server
 | 
			
		||||
 * It sends current routing table and recieves the updated routing table
 | 
			
		||||
 *
 | 
			
		||||
 * @author Ankit
 | 
			
		||||
 */
 | 
			
		||||
class Client extends Thread {
 | 
			
		||||
 | 
			
		||||
    Socket connection;
 | 
			
		||||
    String ipAddress = "";
 | 
			
		||||
    int cost;
 | 
			
		||||
    ObjectInputStream input;
 | 
			
		||||
    ObjectOutputStream output;
 | 
			
		||||
 | 
			
		||||
    public Client(String ip, int cost) throws IOException {
 | 
			
		||||
        ipAddress = ip;
 | 
			
		||||
        this.cost = cost;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings({"unused", "unchecked"})
 | 
			
		||||
    public void run() {
 | 
			
		||||
        try {
 | 
			
		||||
            // connects to the server
 | 
			
		||||
            connection = new Socket(ipAddress, 6969);
 | 
			
		||||
            Connection.neighbors.add(ipAddress);
 | 
			
		||||
            output = new ObjectOutputStream(connection.getOutputStream());
 | 
			
		||||
            input = new ObjectInputStream(connection.getInputStream());
 | 
			
		||||
            System.out.println(InetAddress.getLocalHost().toString()
 | 
			
		||||
                    + " Connected to: " + ipAddress + " with cost: " + cost);
 | 
			
		||||
            if (Connection.table.containsKey(ipAddress)) {
 | 
			
		||||
                if (Connection.table.get(ipAddress) > cost) {
 | 
			
		||||
                    Connection.table.put(ipAddress, cost);
 | 
			
		||||
                    Connection.hop.put(ipAddress, ipAddress);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                Connection.table.put(ipAddress, cost);
 | 
			
		||||
                Connection.hop.put(ipAddress, ipAddress);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            while (true) {
 | 
			
		||||
                Connection.display();
 | 
			
		||||
                HashMap<HashMap<String, Integer>, HashMap<String, String>> sender;
 | 
			
		||||
                sender = new HashMap<HashMap<String, Integer>, HashMap<String, String>>();
 | 
			
		||||
                sender.put(Connection.table, Connection.hop);
 | 
			
		||||
                // sends updated cost and next hop table to the neighbor
 | 
			
		||||
                output.writeObject(sender);
 | 
			
		||||
                output.reset();
 | 
			
		||||
 | 
			
		||||
                HashMap<HashMap<String, Integer>, HashMap<String, String>> receiver;
 | 
			
		||||
                // reads updated cost and next hop table from neighbor
 | 
			
		||||
                receiver = (HashMap<HashMap<String, Integer>, HashMap<String, String>>) input.readObject();
 | 
			
		||||
                HashMap<String, Integer> temp = (HashMap<String, Integer>) receiver.keySet().toArray()[0];
 | 
			
		||||
                HashMap<String, String> tempHop = receiver.get(temp);
 | 
			
		||||
                @SuppressWarnings("rawtypes")
 | 
			
		||||
                Iterator it = temp.entrySet().iterator();
 | 
			
		||||
                Connection.updateTable(temp, ipAddress, tempHop);
 | 
			
		||||
                Thread.sleep(1000);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (UnknownHostException e) {
 | 
			
		||||
            System.out.println("Cannot connect to the network: "
 | 
			
		||||
                    + e.getMessage());
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            System.exit(0);
 | 
			
		||||
        } catch (InterruptedException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        } catch (ClassNotFoundException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								src/test/java/RipV1PacketBuilder.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/test/java/RipV1PacketBuilder.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.io.ByteArrayOutputStream;
 | 
			
		||||
import java.io.DataOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
public class RipV1PacketBuilder {
 | 
			
		||||
 | 
			
		||||
    public static byte[] buildRipV1RequestPacket() throws IOException {
 | 
			
		||||
        // 使用 ByteArrayOutputStream 和 DataOutputStream 来构建数据包
 | 
			
		||||
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 | 
			
		||||
        DataOutputStream dos = new DataOutputStream(baos);
 | 
			
		||||
 | 
			
		||||
        // 1. Command (8比特) - 请求报文,值为 1
 | 
			
		||||
        dos.writeByte(1);  // 请求报文
 | 
			
		||||
 | 
			
		||||
        // 2. Version (8比特) - RIP v1,值为 1
 | 
			
		||||
        dos.writeByte(1);  // RIP v1
 | 
			
		||||
 | 
			
		||||
        // 3. Must be zero (16比特) - 保留字段,必须为零
 | 
			
		||||
        dos.writeShort(0); // 保留字段,填充为零
 | 
			
		||||
 | 
			
		||||
        // 4. Address Family Identifier (AFI) - 请求报文中为 0
 | 
			
		||||
        dos.writeShort(0); // 请求报文的 AFI 为 0
 | 
			
		||||
 | 
			
		||||
        // 5. IP Address (32比特) - 目标 IP 地址,RIP 请求报文中通常为 0.0.0.0
 | 
			
		||||
        InetAddress byName = InetAddress.getByName("200.0.2.0");
 | 
			
		||||
 | 
			
		||||
        // 6. Metric (32比特) - 请求报文的 Metric 为 16,表示不可达
 | 
			
		||||
        dos.writeInt(16); // Metric = 16
 | 
			
		||||
 | 
			
		||||
        // 转换成字节数组
 | 
			
		||||
        return baos.toByteArray();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static byte[] buildRipV1ResponsePacket() throws IOException {
 | 
			
		||||
        // 使用 ByteArrayOutputStream 和 DataOutputStream 来构建数据包
 | 
			
		||||
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 | 
			
		||||
        DataOutputStream dos = new DataOutputStream(baos);
 | 
			
		||||
 | 
			
		||||
        // 1. Command (8比特) - 响应报文,值为 2
 | 
			
		||||
        dos.writeByte(2);  // 响应报文
 | 
			
		||||
 | 
			
		||||
        // 2. Version (8比特) - RIP v1,值为 1
 | 
			
		||||
        dos.writeByte(1);  // RIP v1
 | 
			
		||||
 | 
			
		||||
        // 3. Must be zero (16比特) - 保留字段,必须为零
 | 
			
		||||
        dos.writeShort(0); // 保留字段,填充为零
 | 
			
		||||
 | 
			
		||||
        // 4. Address Family Identifier (AFI) - 请求报文中为 0
 | 
			
		||||
        dos.writeShort(2); // 响应报文的 AFI 对于 IPv4 为 2
 | 
			
		||||
 | 
			
		||||
        dos.writeShort(0);
 | 
			
		||||
 | 
			
		||||
        // 5. IP Address (32比特) - 目标 IP 地址,假设响应报文中为某个 IP
 | 
			
		||||
        InetAddress byName = InetAddress.getByName("200.0.2.0");
 | 
			
		||||
        printByteArray(byName.getAddress());
 | 
			
		||||
 | 
			
		||||
        dos.write(byName.getAddress()); // 192.168.0.1(IPv4 地址)
 | 
			
		||||
 | 
			
		||||
        // 6. Metric (32比特) - 路由的 Metric
 | 
			
		||||
        dos.writeInt(1); // 假设 Metric 为 1
 | 
			
		||||
 | 
			
		||||
        // 转换成字节数组
 | 
			
		||||
        return baos.toByteArray();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) throws IOException {
 | 
			
		||||
        byte[] requestPacket = buildRipV1RequestPacket();
 | 
			
		||||
        byte[] responsePacket = buildRipV1ResponsePacket();
 | 
			
		||||
 | 
			
		||||
        System.out.println("RIP v1 Request Packet: ");
 | 
			
		||||
        printByteArray(requestPacket);
 | 
			
		||||
 | 
			
		||||
        System.out.println("RIP v1 Response Packet: ");
 | 
			
		||||
        printByteArray(responsePacket);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 打印字节数组的辅助函数
 | 
			
		||||
    private static void printByteArray(byte[] byteArray) {
 | 
			
		||||
        for (byte b : byteArray) {
 | 
			
		||||
            System.out.printf("%02X ", b);
 | 
			
		||||
        }
 | 
			
		||||
        System.out.println();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								src/test/java/RipV1Response.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/test/java/RipV1Response.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
import java.net.*;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
public class RipV1Response {
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) {
 | 
			
		||||
        try {
 | 
			
		||||
            // 创建一个数据包
 | 
			
		||||
            byte[] packet = createRipV1ResponsePacket();
 | 
			
		||||
 | 
			
		||||
            // 创建一个UDP Socket
 | 
			
		||||
//            DatagramSocket socket = new DatagramSocket();
 | 
			
		||||
            // 创建一个UDP Socket,并将其绑定到指定的 IP 地址
 | 
			
		||||
            DatagramSocket socket = new DatagramSocket(null);
 | 
			
		||||
            socket.bind(new InetSocketAddress(InetAddress.getByName("192.168.123.45"), 520)); // 使用特定的本地 IP 地址绑定端口
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            InetAddress address = InetAddress.getByName("224.0.0.9"); // RIPv1 默认的多播地址
 | 
			
		||||
 | 
			
		||||
            // 创建一个DatagramPacket并发送
 | 
			
		||||
            DatagramPacket sendPacket = new DatagramPacket(packet, packet.length, address, 520); // RIPv1 默认端口 520
 | 
			
		||||
            socket.send(sendPacket);
 | 
			
		||||
 | 
			
		||||
            System.out.println("RIP v1 Response packet sent!");
 | 
			
		||||
            socket.close();
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 构建RIP v1 响应数据包
 | 
			
		||||
    public static byte[] createRipV1ResponsePacket() {
 | 
			
		||||
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
 | 
			
		||||
        DataOutputStream dos = new DataOutputStream(bos);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // 1. Command (8比特) - 响应报文 (Response)
 | 
			
		||||
            dos.writeByte(2); // Command = 2,表示响应报文
 | 
			
		||||
 | 
			
		||||
            // 2. Version (8比特) - RIP版本号 (RIP-1)
 | 
			
		||||
            dos.writeByte(1); // Version = 1,RIP-1
 | 
			
		||||
 | 
			
		||||
            // 3. Must be zero (16比特) - 保留字段,必须为零
 | 
			
		||||
            dos.writeShort(0); // 16比特的保留字段,填充0
 | 
			
		||||
 | 
			
		||||
            // 4. AFI (Address Family Identifier) (16比特) - 地址族标识符
 | 
			
		||||
            dos.writeShort(2); // AFI = 2,表示 IPv4 地址
 | 
			
		||||
 | 
			
		||||
            dos.writeShort(0);
 | 
			
		||||
 | 
			
		||||
            InetAddress byName = InetAddress.getByName("200.0.2.0");
 | 
			
		||||
            // 5. IP Address (32比特) - 路由目标 IP 地址
 | 
			
		||||
            dos.write(byName.getAddress()); // 192.168.0.1 的 IP 地址(32位)
 | 
			
		||||
 | 
			
		||||
            dos.writeInt(0);
 | 
			
		||||
            dos.writeInt(0);
 | 
			
		||||
            // 6. Metric (32比特) - 路由开销
 | 
			
		||||
            dos.writeInt(1); // Metric = 1,表示一个跳数
 | 
			
		||||
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return bos.toByteArray();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user