├── .idea ├── .gitignore ├── encodings.xml ├── misc.xml ├── modules.xml ├── uiDesigner.xml └── vcs.xml ├── Java Socket ARP.iml ├── README.md ├── map.ser ├── out └── production │ └── Java Socket ARP │ ├── Interface │ ├── ARPAnswerConstants.class │ ├── ARPRequestConstants.class │ ├── DataFrameConstants.class │ └── HandShakeConstants.class │ └── Processes │ ├── AppendKeyValuePairToFile.class │ ├── FileOperation.class │ ├── Host$JTextAreaOutputStream$1.class │ ├── Host$JTextAreaOutputStream.class │ ├── Host$MyWindow$1.class │ ├── Host$MyWindow$2.class │ ├── Host$MyWindow.class │ ├── Host.class │ ├── I_ARP_Table.ser │ ├── J_ARP_Table.ser │ ├── MTable.ser │ ├── MTable.txt │ ├── NTable.ser │ ├── Router$MyWindow$1.class │ ├── Router$MyWindow.class │ ├── Router.class │ ├── RouterReadPipe.class │ ├── RouterReadServer.class │ ├── RouterTrans$1.class │ ├── RouterTrans.class │ ├── Switcher$JTextAreaOutputStream$1.class │ ├── Switcher$JTextAreaOutputStream.class │ ├── Switcher$MyWindow$1.class │ ├── Switcher$MyWindow.class │ ├── Switcher.class │ ├── SwitcherMultiThreadProcess.class │ ├── Table$1.class │ ├── Table$2.class │ ├── Table.class │ └── map.ser └── src ├── Interface ├── ARPAnswerConstants.java ├── ARPRequestConstants.java ├── DataFrameConstants.java └── HandShakeConstants.java └── Processes ├── AppendKeyValuePairToFile.java ├── FileOperation.java ├── Host.java ├── I_ARP_Table.ser ├── J_ARP_Table.ser ├── MTable.ser ├── MTable.txt ├── NTable.ser ├── Router.java ├── RouterReadPipe.java ├── RouterReadServer.java ├── RouterTrans.java ├── Switcher.java ├── SwitcherMultiThreadProcess.java ├── Table.java └── map.ser /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Java Socket ARP.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java_Socket_ARP 2 | 计算机网络ARP模拟 3 | # Windows系统使用者注意: 4 | 本人使用的是MacOS,在运行时没有问题。但是在Windows系统上运行可能会出现BUG。 5 | 6 | Pleasure to have this source code helpful to anyone reading this. 7 | 8 | If helpful, plz give a free star🌟!:D 9 | 10 | If u have any question, plz contact me at countang@outlook.com 11 | 12 | Written by countang. 13 | -------------------------------------------------------------------------------- /map.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/map.ser -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Interface/ARPAnswerConstants.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Interface/ARPAnswerConstants.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Interface/ARPRequestConstants.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Interface/ARPRequestConstants.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Interface/DataFrameConstants.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Interface/DataFrameConstants.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Interface/HandShakeConstants.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Interface/HandShakeConstants.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/AppendKeyValuePairToFile.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/AppendKeyValuePairToFile.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/FileOperation.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/FileOperation.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Host$JTextAreaOutputStream$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Host$JTextAreaOutputStream$1.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Host$JTextAreaOutputStream.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Host$JTextAreaOutputStream.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Host$MyWindow$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Host$MyWindow$1.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Host$MyWindow$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Host$MyWindow$2.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Host$MyWindow.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Host$MyWindow.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Host.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Host.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/I_ARP_Table.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/I_ARP_Table.ser -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/J_ARP_Table.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/J_ARP_Table.ser -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/MTable.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/MTable.ser -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/MTable.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/MTable.txt -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/NTable.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/NTable.ser -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Router$MyWindow$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Router$MyWindow$1.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Router$MyWindow.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Router$MyWindow.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Router.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Router.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/RouterReadPipe.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/RouterReadPipe.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/RouterReadServer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/RouterReadServer.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/RouterTrans$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/RouterTrans$1.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/RouterTrans.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/RouterTrans.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Switcher$JTextAreaOutputStream$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Switcher$JTextAreaOutputStream$1.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Switcher$JTextAreaOutputStream.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Switcher$JTextAreaOutputStream.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Switcher$MyWindow$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Switcher$MyWindow$1.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Switcher$MyWindow.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Switcher$MyWindow.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Switcher.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Switcher.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/SwitcherMultiThreadProcess.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/SwitcherMultiThreadProcess.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Table$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Table$1.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Table$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Table$2.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/Table.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/Table.class -------------------------------------------------------------------------------- /out/production/Java Socket ARP/Processes/map.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/out/production/Java Socket ARP/Processes/map.ser -------------------------------------------------------------------------------- /src/Interface/ARPAnswerConstants.java: -------------------------------------------------------------------------------- 1 | package Interface; 2 | 3 | public interface ARPAnswerConstants { 4 | byte PACKET_TYPE = 2; 5 | byte DEST_MAC_LEN = 6; 6 | byte SOURCE_MAC_LEN = 6; 7 | byte DEST_IP_LEN = 4; 8 | byte SOURCE_IP_LEN = 4; 9 | } 10 | -------------------------------------------------------------------------------- /src/Interface/ARPRequestConstants.java: -------------------------------------------------------------------------------- 1 | package Interface; 2 | 3 | public interface ARPRequestConstants { 4 | byte PACKET_TYPE = 1; 5 | byte DEST_MAC_LEN = 6; 6 | byte SOURCE_MAC_LEN = 6; 7 | byte DEST_IP_LEN = 4; 8 | byte SOURCE_IP_LEN = 4; 9 | } 10 | -------------------------------------------------------------------------------- /src/Interface/DataFrameConstants.java: -------------------------------------------------------------------------------- 1 | package Interface; 2 | 3 | public interface DataFrameConstants { 4 | byte ARP_TYPE = 0; 5 | byte DEST_MAC_LEN = 6; 6 | byte SOURCE_MAC_LEN = 6; 7 | byte DEST_IP_LEN = 4; 8 | byte SOURCE_IP_LEN = 4; 9 | byte DATA_DEF_LEN = 2; 10 | byte DATA_LEN = 0; 11 | 12 | 13 | 14 | 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/Interface/HandShakeConstants.java: -------------------------------------------------------------------------------- 1 | package Interface; 2 | 3 | public interface HandShakeConstants { 4 | byte PACKET_TYPE = 3; 5 | byte INTERFFACE_SYM_LEN = 1; 6 | byte SOURCE_MAC_LEN = 6; 7 | } 8 | -------------------------------------------------------------------------------- /src/Processes/AppendKeyValuePairToFile.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import java.io.*; 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import java.io.*; 7 | import java.util.*; 8 | 9 | public class AppendKeyValuePairToFile { 10 | public static void main(String[] args) { 11 | String fileName = "src/Processes/map.ser"; 12 | // 添加新的键值对 13 | appendKeyValuePairToFile("key3", "value4", fileName); 14 | appendKeyValuePairToFile("key5", "value5", fileName); 15 | 16 | // 读取HashMap 17 | HashMap map = readHashMapFromFile("src/Processes/map.ser"); 18 | System.out.println(map); 19 | } 20 | 21 | public static void appendKeyValuePairToFile(String key, String value, String fileName) { 22 | HashMap map = readHashMapFromFile(fileName); 23 | map.put(key, value); 24 | writeHashMapToFile(map, fileName); 25 | // System.out.println("New key-value pair added to file."); 26 | } 27 | 28 | public static HashMap readHashMapFromFile(String fileName) { 29 | HashMap map = new HashMap<>(); 30 | try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) { 31 | map = (HashMap) ois.readObject(); 32 | } catch (IOException | ClassNotFoundException e) { 33 | // System.out.println("Error reading HashMap from file: " + e.getMessage()); 34 | } 35 | return map; 36 | } 37 | 38 | public static void writeHashMapToFile(HashMap map, String fileName) { 39 | try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) { 40 | oos.writeObject(map); 41 | } catch (IOException e) { 42 | System.out.println("Error writing HashMap to file: " + e.getMessage()); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Processes/FileOperation.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import java.io.*; 3 | import java.util.*; 4 | 5 | public class FileOperation { 6 | public static void writeObject(String path, String Interface, String MAC){ 7 | try { 8 | Map map = new HashMap(); 9 | map.put(Interface, MAC); 10 | 11 | List> list=new ArrayList>(); 12 | FileOutputStream outStream = new FileOutputStream(path, true); 13 | ObjectOutputStream objectOutputStream = new ObjectOutputStream(outStream); 14 | 15 | objectOutputStream.writeObject(map); 16 | outStream.close(); 17 | System.out.println("successful"); 18 | } catch (Exception e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | //清空文件内容 23 | public static void clearFile(String path){ 24 | try { 25 | FileWriter fileWriter = new FileWriter(path); 26 | fileWriter.write(""); 27 | fileWriter.close(); 28 | } catch (IOException e) { 29 | e.printStackTrace(); 30 | } 31 | } 32 | 33 | public static List> readObject(String path){ 34 | FileInputStream freader; 35 | try { 36 | freader = new FileInputStream(path); 37 | FileOutputStream fos = null; 38 | HashMap map; 39 | List> hashMapList = new ArrayList>(); 40 | ObjectInputStream objectInputStream = null; 41 | Object ois = objectInputStream.readObject(); 42 | while(ois != null){ 43 | map = (HashMap)ois; 44 | hashMapList.add(map); 45 | ois = objectInputStream.readObject(); 46 | } 47 | return hashMapList; 48 | } catch (FileNotFoundException e) { 49 | // TODO Auto-generated catch block 50 | e.printStackTrace(); 51 | } catch (IOException e) { 52 | // TODO Auto-generated catch block 53 | e.printStackTrace(); 54 | } catch (ClassNotFoundException e) { 55 | // TODO Auto-generated catch block 56 | e.printStackTrace(); 57 | } 58 | return null; 59 | } 60 | public static void main(String[] args) { 61 | FileOperation fileTest = new FileOperation(); 62 | System.out.println(fileTest.readObject("src/Processes/Mtable.txt")); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Processes/Host.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import java.awt.*; 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.*; 6 | import java.net.Socket; 7 | import java.util.*; 8 | import java.util.List; 9 | import javax.swing.*; 10 | import javax.swing.table.DefaultTableModel; 11 | import javax.swing.table.TableColumnModel; 12 | 13 | import static Processes.AppendKeyValuePairToFile.readHashMapFromFile; 14 | import static Processes.SwitcherMultiThreadProcess.byte2ToInt; 15 | import static Processes.SwitcherMultiThreadProcess.byteArrayToIp; 16 | import static Processes.Table.Sym_IP_Table; 17 | import static Processes.Table.Sym_Mac_Table; 18 | 19 | 20 | public class Host extends Thread{ 21 | public static char Host_Sym; 22 | private static String Switcher_Interface; 23 | private static String Host_IP; 24 | private static String Host_MAC; 25 | private static Socket Host_Socket; 26 | private static volatile String Data; 27 | private static volatile char Send_Sym; 28 | 29 | public static volatile HashMap ARP_Table = new HashMap<>(); 30 | private static volatile MyWindow myWindow; 31 | 32 | public Host(){ 33 | } 34 | public Host(Socket socket){ 35 | Host_Socket = socket; 36 | } 37 | 38 | public Host(String IP, String MAC, char Sym, String Interface){ 39 | Host_IP = IP; 40 | Host_MAC = MAC; 41 | Host_Sym = Sym; 42 | Switcher_Interface = Interface; 43 | } 44 | 45 | //将IP地址转化为字节数组 46 | public static byte[] ipToByteArray(String ip) { 47 | String[] split = ip.split("\\."); 48 | byte[] bs = new byte[4]; 49 | for (int i=0; i < split.length; i++) { 50 | bs[i] = (byte)Integer.parseInt(split[i]); 51 | } 52 | return bs; 53 | } 54 | 55 | /** 56 | * 将Mac地址字符串转换为byte数组 57 | * @param mac Mac地址字符串,格式如:78:44:fd:c9:87:a0 58 | * @return 该Mac地址的byte数组形式 59 | */ 60 | static byte[] MacToByte(String mac) { 61 | byte[] macBytes = new byte[6]; 62 | 63 | String[] strArr = mac.split("-"); 64 | for (int i = 0; i < strArr.length; i++) { 65 | int value = Integer.parseInt(strArr[i], 16); 66 | macBytes[i] = (byte) value; 67 | } 68 | return macBytes; 69 | } 70 | /** 71 | * 将Mac地址的数组形式转换为字符串形式 72 | * @param macBytes mac地址的数组形式 73 | * @return Mac地址的字符串,格式如:78-44-fd-c9-87-a0 74 | */ 75 | static String byteToMac(byte[] macBytes) { 76 | StringBuilder builder = new StringBuilder(); 77 | for (int i = 0; i < macBytes.length; i++) { 78 | builder.append('-').append(Integer.toHexString(0xFF & macBytes[i])); 79 | } 80 | return builder.substring(1); 81 | } 82 | 83 | public static byte[] unsignedShortToByte2(int s) { 84 | byte[] targets = new byte[2]; 85 | targets[0] = (byte) (s >> 8 & 0xFF); 86 | targets[1] = (byte) (s & 0xFF); 87 | return targets; 88 | } 89 | 90 | 91 | //开启子线程来接受发给主机的信息 92 | @Override 93 | public void run(){ 94 | BufferedInputStream dataInputStream = null; 95 | try { 96 | dataInputStream = new BufferedInputStream(Host_Socket.getInputStream()); 97 | while(true){ 98 | byte[] by = new byte[1]; 99 | dataInputStream.read(by); 100 | byte Frame_type = by[0]; 101 | if(Frame_type == 0){ 102 | byte[] byte_before_data = new byte[22]; 103 | dataInputStream.read(byte_before_data); 104 | byte[] Dest_Mac = Arrays.copyOfRange(byte_before_data, 0, 6); 105 | byte[] Src_Mac = Arrays.copyOfRange(byte_before_data, 6, 12); 106 | byte[] Dest_IP = Arrays.copyOfRange(byte_before_data, 12, 16); 107 | byte[] Src_IP = Arrays.copyOfRange(byte_before_data, 16, 20); 108 | byte[] Data_length = Arrays.copyOfRange(byte_before_data, 20, 22); 109 | int Data_length_int = byte2ToInt(Data_length, 0); 110 | byte[] data = new byte[Data_length_int]; 111 | dataInputStream.read(data); 112 | String Data_str = new String(data); 113 | String Dest_Mac_str = byteToMac(Dest_Mac); 114 | String Src_Mac_str = byteToMac(Src_Mac); 115 | String Dest_IP_str = byteArrayToIp(Dest_IP); 116 | String Src_IP_str = byteArrayToIp(Src_IP); 117 | System.out.println("获取到报文类型为:数据报文,\n目的MAC地址为" + Dest_Mac_str + ",源MAC地址为" + Src_Mac_str + ",\n目的IP地址为" + Dest_IP_str + ",源IP地址为" + Src_IP_str + ",\n数据长度为" + Data_length_int + ",数据为" + Data_str + "\n"); 118 | } 119 | else if (Frame_type == 1) { 120 | // System.out.println("x获取到报文类型为:ARP请求报文"); 121 | // System.out.println("Host_IP:" + this.Host_IP); 122 | byte[] ARPRequest = new byte[20]; 123 | dataInputStream.read(ARPRequest); 124 | byte[] Dest_Mac = Arrays.copyOfRange(ARPRequest, 0, 6); 125 | byte[] Src_Mac = Arrays.copyOfRange(ARPRequest, 6, 12); 126 | byte[] Dest_IP = Arrays.copyOfRange(ARPRequest, 12, 16); 127 | byte[] Src_IP = Arrays.copyOfRange(ARPRequest, 16, 20); 128 | String Dest_Mac_str = byteToMac(Dest_Mac); 129 | String Src_Mac_str = byteToMac(Src_Mac); 130 | String Dest_IP_str = byteArrayToIp(Dest_IP); 131 | String Src_IP_str = byteArrayToIp(Src_IP); 132 | // System.out.println("Dest_IP:" + Dest_IP_str); 133 | if (Dest_IP_str.equals(Host_IP)) { 134 | char sym_src = 0; 135 | for (char getKey : Sym_IP_Table.keySet()) { 136 | if (Sym_IP_Table.get(getKey).equals(Src_IP_str)) { 137 | sym_src = getKey; 138 | } 139 | } 140 | char sym_dest = 0; 141 | for (char getKey : Sym_IP_Table.keySet()) { 142 | if (Sym_IP_Table.get(getKey).equals(Dest_IP_str)) { 143 | sym_dest = getKey; 144 | } 145 | } 146 | Dest_Mac_str = Host_MAC; 147 | System.out.println("收到来自" + Src_IP_str + "的ARP请求"); 148 | String IP_Next = Src_IP_str; 149 | String Mac_Next = Src_Mac_str; 150 | if (((sym_src == 'A' || sym_src == 'B' || sym_src == 'C') && (sym_dest == 'D' || sym_dest == 'F')) || 151 | ((sym_src == 'D' || sym_src == 'F') && (sym_dest == 'A' || sym_dest == 'B' || sym_dest == 'C'))) { 152 | if (sym_src == 'A' || sym_src == 'B' || sym_src == 'C') { 153 | IP_Next = "202.119.65.100"; 154 | Mac_Next = "19-10-22-ED-87-78"; 155 | } else if (sym_src == 'D' || sym_src == 'F') { 156 | IP_Next = "202.119.64.100"; 157 | Mac_Next = "17-10-22-ED-87-78"; 158 | } 159 | } 160 | 161 | if(!ARP_Table.containsKey(Src_IP_str)){ 162 | myWindow.addData(IP_Next, Mac_Next); 163 | } 164 | System.out.println("发送ARP响应报文\n"); 165 | SendARPReply(Src_Mac_str, Host_MAC, Src_IP_str, Host_IP); 166 | } 167 | } 168 | //收到ARP响应报文 169 | else if (Frame_type == 2) 170 | { 171 | byte[] ARPReply = new byte[20]; 172 | dataInputStream.read(ARPReply); 173 | byte[] Dest_Mac = Arrays.copyOfRange(ARPReply, 0, 6); 174 | byte[] Src_Mac = Arrays.copyOfRange(ARPReply, 6, 12); 175 | byte[] Dest_IP = Arrays.copyOfRange(ARPReply, 12, 16); 176 | byte[] Src_IP = Arrays.copyOfRange(ARPReply, 16, 20); 177 | String Dest_Mac_str = byteToMac(Dest_Mac); 178 | String Src_Mac_str = byteToMac(Src_Mac); 179 | String Dest_IP_str = byteArrayToIp(Dest_IP); 180 | String Src_IP_str = byteArrayToIp(Src_IP); 181 | if(Dest_IP_str.equals(Host_IP)){ 182 | char sym_src = 0; 183 | for(char getKey: Sym_IP_Table.keySet()){ 184 | if(Sym_IP_Table.get(getKey).equals(Src_IP_str)){ 185 | sym_src = getKey; 186 | } 187 | } 188 | char sym_dest = 0; 189 | for(char getKey: Sym_IP_Table.keySet()){ 190 | if(Sym_IP_Table.get(getKey).equals(Dest_IP_str)){ 191 | sym_dest = getKey; 192 | } 193 | } 194 | String IP_Next = Src_IP_str; 195 | String Mac_Next = Src_Mac_str; 196 | if(((sym_src == 'A' || sym_src == 'B' || sym_src == 'C') && (sym_dest == 'D' || sym_dest == 'F' )) || 197 | ((sym_src == 'D' || sym_src == 'F') && (sym_dest == 'A' || sym_dest == 'B' || sym_dest == 'C'))) 198 | { 199 | if(sym_src == 'A' || sym_src == 'B' || sym_src == 'C'){ 200 | IP_Next = "202.119.65.100"; 201 | Mac_Next = "19-10-22-ED-87-78"; 202 | } 203 | else if(sym_src == 'D' || sym_src == 'F'){ 204 | IP_Next = "202.119.64.100"; 205 | Mac_Next = "17-10-22-ED-87-78"; 206 | } 207 | } 208 | 209 | myWindow.addData(IP_Next, Mac_Next); 210 | //// System.out.println("ARP表更新成功为"); 211 | // //输出ARP表 212 | // for(String getKey: ARP_Table.keySet()){ 213 | // System.out.println(getKey + " " + ARP_Table.get(getKey)); 214 | // } 215 | System.out.println("收到来自" + Src_IP_str + "的ARP应答\n"); 216 | } 217 | } 218 | // else if(Frame_type == 3){ 219 | // byte[] handShake = new byte[8]; 220 | // dataInputStream.read(handShake); 221 | // byte[] byte_Interface = Arrays.copyOfRange(handShake, 0, 2); 222 | // String Interface_sym = new String(byte_Interface); 223 | // byte[] MAC = Arrays.copyOfRange(handShake, 2, 8); 224 | // String mac_str = byteToMac(MAC); 225 | // } 226 | } 227 | } catch (IOException e) { 228 | throw new RuntimeException(e); 229 | } 230 | } 231 | 232 | //发送握手报文 233 | private void HandShake() throws IOException { 234 | // boolean isConnected = Host_Socket.isConnected(); 235 | // System.out.println(isConnected); 236 | System.out.println("主机" + Host_Sym + "握手成功。"); 237 | System.out.println("主机" + Host_Sym + "的IP地址为:" + Host_IP); 238 | System.out.println("主机" + Host_Sym + "的MAC地址为:" + Host_MAC + "\n"); 239 | OutputStream outputStream = Host_Socket.getOutputStream(); 240 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 241 | BufferedReader reader = new BufferedReader(new InputStreamReader(Host_Socket.getInputStream())); 242 | byte Frame_type = (byte)3; 243 | byte[] Interface = Switcher_Interface.getBytes(); 244 | byte[] MAC = MacToByte(Host_MAC); 245 | // byte[] byteIP = ipToByteArray(Host_IP); 246 | dataOutputStream.write(Frame_type); 247 | dataOutputStream.write(Interface); 248 | dataOutputStream.write(MAC); 249 | // dataOutputStream.write(byteIP); 250 | dataOutputStream.flush(); 251 | } 252 | 253 | private void SendDataGram() throws IOException { 254 | // Scanner scan = new Scanner(System.in); 255 | Data = null; 256 | // System.out.println("请输入要发送的数据信息:"); 257 | while(Data == null){ 258 | } 259 | Send_Sym = 0; 260 | while(Send_Sym == 0){ 261 | } 262 | byte[] byte_data = Data.getBytes(); 263 | int data_length = byte_data.length; 264 | byte[] byte_data_length = unsignedShortToByte2(data_length); 265 | 266 | String Dest_IP = Sym_IP_Table.get(Send_Sym); 267 | byte[] byte_Dest_IP = ipToByteArray(Dest_IP); 268 | byte[] byte_Source_IP = ipToByteArray(Host_IP); 269 | String Dest_MAC; 270 | byte[] byte_Dest_MAC = null; 271 | String Dest_Router_IP = null; 272 | boolean Cross_Router = false; 273 | if(((Host_Sym == 'A' || Host_Sym == 'B' || Host_Sym == 'C') && (Send_Sym == 'D' || Send_Sym == 'F')) || 274 | ((Host_Sym == 'D' || Host_Sym == 'F') && (Send_Sym == 'A' || Send_Sym == 'B' || Send_Sym == 'C'))) { 275 | if (Host_Sym == 'A' || Host_Sym == 'B' || Host_Sym == 'C') 276 | { 277 | Dest_Router_IP = "202.119.64.100"; 278 | Cross_Router = true; 279 | } 280 | else{ 281 | Dest_Router_IP = "202.119.65.100"; 282 | Cross_Router = true; 283 | } 284 | } 285 | 286 | while(true){ 287 | boolean flag_MAC = false; 288 | for(String getKey: ARP_Table.keySet()){ 289 | if(!Cross_Router){ 290 | if (getKey.equals(Dest_IP)) { 291 | flag_MAC = true; 292 | break; 293 | } 294 | } 295 | else { 296 | if (getKey.equals(Dest_Router_IP)) { 297 | flag_MAC = true; 298 | break; 299 | } 300 | } 301 | } 302 | if(flag_MAC){ 303 | break; 304 | } 305 | System.out.println("ARP高速缓存中没有下一跳地址,正在发送ARP请求报文..."); 306 | SendARPRequest(Host_Sym, Send_Sym); 307 | try { 308 | Thread.sleep(1000); 309 | } catch (InterruptedException e) { 310 | e.printStackTrace(); 311 | } 312 | } 313 | 314 | 315 | if(byte_Dest_IP[2] == byte_Source_IP[2]){ 316 | System.out.println("目的主机在同一网络中..."); 317 | String Interface_str = null; 318 | switch (Send_Sym){ 319 | case 'D': 320 | case 'A': 321 | Interface_str = "E0"; 322 | break; 323 | case 'F': 324 | case 'B': 325 | Interface_str = "E1"; 326 | break; 327 | case 'C': 328 | Interface_str = "E2"; 329 | break; 330 | } 331 | if(Send_Sym == 'A' || Send_Sym == 'B' || Send_Sym == 'C'){ 332 | Dest_MAC = readHashMapFromFile("src/Processes/MTable.ser").get(Interface_str); 333 | } 334 | else{ 335 | Dest_MAC = readHashMapFromFile("src/Processes/NTable.ser").get(Interface_str); 336 | } 337 | } 338 | else{ 339 | System.out.println("目的主机不在同一网络中..."); 340 | if(Host_Sym == 'A' || Host_Sym == 'B' || Host_Sym == 'C'){ 341 | Dest_MAC = "17-10-22-ED-87-78"; 342 | } 343 | else{ 344 | Dest_MAC = "19-10-22-ED-87-78"; 345 | } 346 | } 347 | byte_Dest_MAC = MacToByte(Dest_MAC); 348 | 349 | OutputStream outputStream = Host_Socket.getOutputStream(); 350 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 351 | // BufferedReader reader = new BufferedReader(new InputStreamReader(Host_Socket.getInputStream())); 352 | byte Frame_type = (byte)0; 353 | byte[] byte_Source_Mac = MacToByte(Host_MAC); 354 | // byte[] byteIP = ipToByteArray(Host_IP); 355 | dataOutputStream.write(Frame_type); 356 | dataOutputStream.write(byte_Dest_MAC); 357 | dataOutputStream.write(byte_Source_Mac); 358 | dataOutputStream.write(byte_Dest_IP); 359 | dataOutputStream.write(byte_Source_IP); 360 | dataOutputStream.write(byte_data_length); 361 | dataOutputStream.write(byte_data); 362 | // dataOutputStream.write(byteIP); 363 | dataOutputStream.flush(); 364 | // System.out.println(ARP_Table.get(0).getFirst()); 365 | System.out.println("数据发送成功。\n"); 366 | } 367 | 368 | private void SendARPRequest(char source_sym, char dest_sym) throws IOException { 369 | if (((source_sym == 'A' || source_sym == 'B' || source_sym == 'C') && (dest_sym == 'D' || dest_sym == 'F')) || 370 | ((source_sym == 'D' || source_sym == 'F') && (dest_sym == 'A' || dest_sym == 'B' || dest_sym == 'C'))) 371 | { 372 | System.out.println("ARP请求对象不在同一个网络中,将ARP请求发送给路由器..."); 373 | String Dest_MAC = "00-00-00-00-00-00"; 374 | byte[] byte_Dest_MAC = MacToByte(Dest_MAC); 375 | String Source_MAC = Host_MAC; 376 | byte[] byte_Source_MAC = MacToByte(Source_MAC); 377 | String Dest_IP; 378 | if(source_sym == 'A' || source_sym == 'B' || source_sym == 'C'){ 379 | Dest_IP = "202.119.64.100"; //路由器M的E0端口IP 380 | } 381 | else{ 382 | Dest_IP = "202.119.65.100"; //路由器N的E0端口IP 383 | } 384 | 385 | 386 | byte[] byte_Dest_IP = ipToByteArray(Dest_IP); 387 | byte[] byte_Source_IP = ipToByteArray(Host_IP); 388 | 389 | OutputStream outputStream = Host_Socket.getOutputStream(); 390 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 391 | byte Frame_type = (byte) 1; 392 | dataOutputStream.write(Frame_type); 393 | dataOutputStream.write(byte_Dest_MAC); 394 | dataOutputStream.write(byte_Source_MAC); 395 | dataOutputStream.write(byte_Dest_IP); 396 | dataOutputStream.write(byte_Source_IP); 397 | dataOutputStream.flush(); 398 | } 399 | else { 400 | System.out.println("ARP请求对象在同一个网络中..."); 401 | String Dest_MAC = "00-00-00-00-00-00"; 402 | byte[] byte_Dest_MAC = MacToByte(Dest_MAC); 403 | String Source_MAC = Host_MAC; 404 | byte[] byte_Source_MAC = MacToByte(Source_MAC); 405 | String Dest_IP = Sym_IP_Table.get(dest_sym); 406 | byte[] byte_Dest_IP = ipToByteArray(Dest_IP); 407 | byte[] byte_Source_IP = ipToByteArray(Host_IP); 408 | 409 | OutputStream outputStream = Host_Socket.getOutputStream(); 410 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 411 | byte Frame_type = (byte) 1; 412 | dataOutputStream.write(Frame_type); 413 | dataOutputStream.write(byte_Dest_MAC); 414 | dataOutputStream.write(byte_Source_MAC); 415 | dataOutputStream.write(byte_Dest_IP); 416 | dataOutputStream.write(byte_Source_IP); 417 | dataOutputStream.flush(); 418 | } 419 | } 420 | 421 | private void SendARPReply(String Dest_Mac_Str, String Src_Mac_Str, String Dest_IP_Str, String Src_IP_Str) throws IOException { 422 | System.out.println("本主机正在发送ARP应答报文..."); 423 | byte[] byte_Dest_MAC = MacToByte(Dest_Mac_Str); 424 | byte[] byte_Source_MAC = MacToByte(Src_Mac_Str); 425 | byte[] byte_Dest_IP = ipToByteArray(Dest_IP_Str); 426 | byte[] byte_Source_IP = ipToByteArray(Src_IP_Str); 427 | OutputStream outputStream = Host_Socket.getOutputStream(); 428 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 429 | byte Frame_type = (byte) 2; 430 | dataOutputStream.write(Frame_type); 431 | dataOutputStream.write(byte_Dest_MAC); 432 | dataOutputStream.write(byte_Source_MAC); 433 | dataOutputStream.write(byte_Dest_IP); 434 | dataOutputStream.write(byte_Source_IP); 435 | dataOutputStream.flush(); 436 | } 437 | 438 | //init host 439 | private void SetHost() throws IOException { 440 | // System.out.println("请输入要建立连接的主机IP地址、MAC地址以及主机标识符:"); 441 | // Scanner scan = new Scanner(System.in); 442 | // String ip = scan.nextLine(); 443 | // String MAC = scan.nextLine(); 444 | String Interface = null; 445 | // char sym = (char)System.in.read(); 446 | // scan.nextLine(); 447 | char sym = Host_Sym; 448 | switch (sym){ 449 | case 'D': 450 | case 'A': Interface = "E0"; 451 | break; 452 | case 'F': 453 | case 'B': Interface = "E1"; 454 | break; 455 | case 'C': Interface = "E2"; 456 | break; 457 | } 458 | Host_IP = Sym_IP_Table.get(sym); 459 | Host_MAC = Sym_Mac_Table.get(sym); 460 | Switcher_Interface = Interface; 461 | } 462 | 463 | public static class MyWindow extends JFrame { 464 | private boolean isRunning = true; 465 | private final JComboBox comboBox; 466 | private final JTextArea textArea; 467 | private DefaultTableModel model; 468 | public void updateTableData() { 469 | model.setRowCount(0); 470 | for (String key : ARP_Table.keySet()) { 471 | model.addRow(new Object[]{key, ARP_Table.get(key)}); 472 | } 473 | model.fireTableDataChanged(); 474 | } 475 | public void addData(String key, String value) { 476 | ARP_Table.put(key, value); 477 | updateTableData(); 478 | } 479 | 480 | // 删除哈希表中的数据并更新表格 481 | public void removeData(String key) { 482 | ARP_Table.remove(key); 483 | updateTableData(); 484 | } 485 | 486 | 487 | 488 | public MyWindow(Host host) { 489 | myWindow = this; 490 | JFrame.setDefaultLookAndFeelDecorated(true); 491 | // 设置窗口属性 492 | setTitle("主机"); 493 | setSize(600, 350); 494 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 495 | setLocationRelativeTo(null); 496 | 497 | // 创建下拉框 498 | String[] options = {"A", "B", "C", "D", "F"}; 499 | comboBox = new JComboBox<>(options); 500 | 501 | // 创建按钮 502 | JButton button = new JButton("启动主机"); 503 | button.addActionListener(new ActionListener() { 504 | @Override 505 | public void actionPerformed(ActionEvent e) { 506 | String option = (String) comboBox.getSelectedItem(); 507 | // 在文本框中显示结果 508 | // textArea.append("Option selected: " + option + "\n"); 509 | Host_Sym = option.charAt(0); 510 | new Thread(()->{ 511 | try { 512 | System.out.println("主机" + Host_Sym + "开始运行..."); 513 | connect(host); 514 | } catch (IOException ex) { 515 | throw new RuntimeException(ex); 516 | } 517 | }).start(); 518 | } 519 | }); 520 | //创建一个文本输入框 521 | JTextField textField_Data = new JTextField(20); 522 | 523 | String[] Data_Send_Sym_options = {"A", "B", "C", "D", "F"}; 524 | JComboBox Data_Send_comboBox = new JComboBox<>(Data_Send_Sym_options); 525 | 526 | // 创建按钮 527 | JButton Send_Data_button = new JButton("Send Data"); 528 | Send_Data_button.addActionListener(new ActionListener() { 529 | @Override 530 | public void actionPerformed(ActionEvent e) { 531 | String option = (String) Data_Send_comboBox.getSelectedItem(); 532 | if(Objects.equals(option, comboBox.getSelectedItem())){ 533 | return; 534 | } 535 | String text = textField_Data.getText(); 536 | Data = text; 537 | textField_Data.setText(""); 538 | // 在文本框中显示结果 539 | Send_Sym = option.charAt(0); 540 | } 541 | }); 542 | 543 | 544 | 545 | // 创建文本框 546 | textArea = new JTextArea(10, 30); 547 | textArea.setEditable(false); 548 | JScrollPane scrollPane = new JScrollPane(textArea); 549 | JLabel label_Choose_Host = new JLabel(" 请选择要启动的主机:"); 550 | JLabel label_Choose_Send_Host = new JLabel("目标主机:"); 551 | JLabel label_Data = new JLabel("发送数据:"); 552 | JLabel ARP_Label = new JLabel("ARP高速缓存表"); 553 | 554 | model = new DefaultTableModel(new Object[]{"Key", "Value"}, 0); 555 | ARP_Table.put(" IP地址", " MAC地址"); 556 | 557 | // 将哈希表数据添加到表格模型中 558 | for (String key : ARP_Table.keySet()) { 559 | model.addRow(new Object[]{key, ARP_Table.get(key)}); 560 | } 561 | JTable table = new JTable(model); 562 | TableColumnModel columnModel = table.getColumnModel(); 563 | columnModel.getColumn(0).setPreferredWidth(110); 564 | columnModel.getColumn(1).setPreferredWidth(135); 565 | 566 | // 添加组件到窗口 567 | JPanel panel = new JPanel(); 568 | panel.add(ARP_Label); 569 | panel.add(label_Choose_Host); 570 | panel.add(comboBox); 571 | panel.add(button); 572 | JPanel panel1 = new JPanel(); 573 | JPanel panel2 = new JPanel(); 574 | panel2.add(table); 575 | panel1.add(label_Choose_Send_Host); 576 | panel1.add(Data_Send_comboBox); 577 | panel1.add(label_Data); 578 | panel1.add(textField_Data); 579 | panel1.add(Send_Data_button); 580 | add(panel, BorderLayout.NORTH); 581 | add(panel2, BorderLayout.WEST); 582 | add(panel1, BorderLayout.AFTER_LAST_LINE); 583 | add(scrollPane, BorderLayout.CENTER); 584 | JTextAreaOutputStream out = new JTextAreaOutputStream(textArea); 585 | System.setOut(new PrintStream(out));//设置输出重定向 586 | 587 | // 显示窗口 588 | setVisible(true); 589 | } 590 | } 591 | //将输出流重定向到界面 592 | static class JTextAreaOutputStream extends OutputStream 593 | { 594 | private final JTextArea destination; 595 | public JTextAreaOutputStream (JTextArea destination) 596 | { 597 | if (destination == null) 598 | throw new IllegalArgumentException ("Destination is null"); 599 | this.destination = destination; 600 | } 601 | @Override 602 | public void write(byte[] buffer, int offset, int length) throws IOException 603 | { 604 | final String text = new String (buffer, offset, length); 605 | SwingUtilities.invokeLater(new Runnable () 606 | { 607 | @Override 608 | public void run() 609 | { 610 | destination.append (text); 611 | } 612 | }); 613 | } 614 | @Override 615 | public void write(int b) throws IOException 616 | { 617 | write (new byte [] {(byte)b}, 0, 1); 618 | } 619 | } 620 | 621 | public static void connect(Host host) throws IOException { 622 | if (Host_Sym == 'A' || Host_Sym == 'B' || Host_Sym == 'C') { 623 | Host_Socket = new Socket("localhost", 9998); 624 | } else { 625 | Host_Socket = new Socket("localhost", 9997); 626 | } 627 | host.SetHost(); 628 | 629 | Host sonThread = new Host(Host_Socket); 630 | sonThread.start(); 631 | host.HandShake(); 632 | while (true) { 633 | host.SendDataGram(); 634 | } 635 | } 636 | 637 | 638 | 639 | 640 | 641 | 642 | public static void main(String[] args) throws IOException { 643 | Host host = new Host(); 644 | MyWindow window = new MyWindow(host); 645 | } 646 | } -------------------------------------------------------------------------------- /src/Processes/I_ARP_Table.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/src/Processes/I_ARP_Table.ser -------------------------------------------------------------------------------- /src/Processes/J_ARP_Table.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/src/Processes/J_ARP_Table.ser -------------------------------------------------------------------------------- /src/Processes/MTable.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/src/Processes/MTable.ser -------------------------------------------------------------------------------- /src/Processes/MTable.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/src/Processes/MTable.txt -------------------------------------------------------------------------------- /src/Processes/NTable.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/src/Processes/NTable.ser -------------------------------------------------------------------------------- /src/Processes/Router.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import javax.swing.*; 3 | import javax.swing.table.DefaultTableModel; 4 | import javax.swing.table.TableColumnModel; 5 | import java.awt.*; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.io.*; 9 | import java.net.Socket; 10 | import java.util.*; 11 | import java.util.List; 12 | 13 | import static Processes.AppendKeyValuePairToFile.readHashMapFromFile; 14 | import static Processes.FileOperation.clearFile; 15 | import static Processes.Host.MacToByte; 16 | 17 | public class Router extends Thread{ 18 | public volatile static char Router_Sym; 19 | private static String Switcher_Interface; 20 | public volatile static String Interface_E0_IP; 21 | public volatile static String Interface_E1_IP; 22 | private volatile static Socket Socket_Ex; 23 | public volatile static String Interface_E0_MAC; 24 | public volatile static String Interface_E1_MAC; 25 | public static volatile MyWindow myWindow; 26 | 27 | 28 | 29 | public static byte[] ipToByteArray(String ip) { 30 | String[] split = ip.split("\\."); 31 | byte[] bs = new byte[4]; 32 | for (int i=0; i < split.length; i++) { 33 | bs[i] = (byte)Integer.parseInt(split[i]); 34 | } 35 | return bs; 36 | } 37 | public Router(){ 38 | } 39 | 40 | private void SetRouter() throws IOException { 41 | if(Router_Sym == 'I'){ 42 | Switcher_Interface = "E3"; 43 | Interface_E0_IP = "202.119.64.100"; 44 | Interface_E1_IP = "202.119.66.100"; 45 | Interface_E0_MAC = "17-10-22-ED-87-78"; 46 | Interface_E1_MAC = "18-10-22-ED-87-78"; 47 | } 48 | else { 49 | Switcher_Interface = "E2"; 50 | Interface_E0_IP = "202.119.65.100"; 51 | Interface_E1_IP = "202.119.66.101"; 52 | Interface_E0_MAC = "19-10-22-ED-87-78"; 53 | Interface_E1_MAC = "20-10-22-ED-87-78"; 54 | } 55 | } 56 | 57 | //与交换机进行握手 58 | private void HandShake() throws IOException { 59 | // boolean isConnected = Socket_Ex.isConnected(); 60 | // System.out.println(isConnected); 61 | System.out.println("路由器" + Router_Sym + "握手成功。"); 62 | OutputStream outputStream = Socket_Ex.getOutputStream(); 63 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 64 | BufferedReader reader = new BufferedReader(new InputStreamReader(Socket_Ex.getInputStream())); 65 | byte Frame_type = (byte)3; 66 | byte[] Interface = Switcher_Interface.getBytes(); 67 | byte[] MAC = MacToByte(Interface_E0_MAC); 68 | // byte[] byteIP = ipToByteArray(Host_IP); 69 | dataOutputStream.write(Frame_type); 70 | dataOutputStream.write(Interface); 71 | dataOutputStream.write(MAC); 72 | // dataOutputStream.write(byteIP); 73 | dataOutputStream.flush(); 74 | } 75 | 76 | public static class MyWindow extends JFrame { 77 | private final JComboBox comboBox; 78 | private final JTextArea textArea; 79 | private DefaultTableModel model; 80 | 81 | public void updateTableData() { 82 | model.setRowCount(0); 83 | String file_path; 84 | if(Router_Sym == 'I'){ 85 | file_path = "src/Processes/I_ARP_Table.ser"; 86 | } 87 | else { 88 | file_path = "src/Processes/J_ARP_Table.ser"; 89 | } 90 | for (String key : readHashMapFromFile(file_path).keySet()) { 91 | model.addRow(new Object[]{key, readHashMapFromFile(file_path).get(key)}); 92 | } 93 | model.fireTableDataChanged(); 94 | } 95 | public void addData(String key, String value) { 96 | String file_path; 97 | if(Router_Sym == 'I'){ 98 | file_path = "src/Processes/I_ARP_Table.ser"; 99 | } 100 | else { 101 | file_path = "src/Processes/J_ARP_Table.ser"; 102 | } 103 | readHashMapFromFile(file_path).put(key, value); 104 | updateTableData(); 105 | } 106 | 107 | public MyWindow(Router router) { 108 | myWindow = this; 109 | JFrame.setDefaultLookAndFeelDecorated(true); 110 | // 设置窗口属性 111 | setTitle("路由器"); 112 | setSize(550, 300); 113 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 114 | setLocationRelativeTo(null); 115 | 116 | // 创建下拉框 117 | String[] options = {"I", "J"}; 118 | comboBox = new JComboBox<>(options); 119 | 120 | // 创建按钮 121 | JButton button = new JButton("启动路由器"); 122 | button.addActionListener(new ActionListener() { 123 | @Override 124 | public void actionPerformed(ActionEvent e) { 125 | String option = (String) comboBox.getSelectedItem(); 126 | // 在文本框中显示结果 127 | // textArea.append("Option selected: " + option + "\n"); 128 | Router_Sym = option.charAt(0); 129 | new Thread(()->{ 130 | try { 131 | System.out.println("路由器" + Router_Sym + "开始运行..."); 132 | router.StartRouter(router); 133 | } catch (IOException ex) { 134 | throw new RuntimeException(ex); 135 | } 136 | }).start(); 137 | } 138 | }); 139 | 140 | // 创建文本框 141 | textArea = new JTextArea(10, 30); 142 | textArea.setEditable(false); 143 | JScrollPane scrollPane = new JScrollPane(textArea); 144 | JLabel label_Choose_Switcher = new JLabel(" 请选择要启动的路由器:"); 145 | JLabel ARP_Label = new JLabel("ARP高速缓存表 "); 146 | 147 | model = new DefaultTableModel(new Object[]{"Key", "Value"}, 0); 148 | model.addRow(new Object[]{" IP地址", " MAC地址"}); 149 | 150 | // 将哈希表数据添加到表格模型中 151 | JTable table = new JTable(model); 152 | TableColumnModel columnModel = table.getColumnModel(); 153 | columnModel.getColumn(0).setPreferredWidth(110); 154 | columnModel.getColumn(1).setPreferredWidth(135); 155 | 156 | 157 | // 添加组件到窗口 158 | JPanel panel = new JPanel(); 159 | panel.add(ARP_Label); 160 | panel.add(label_Choose_Switcher); 161 | panel.add(comboBox); 162 | panel.add(button); 163 | JPanel panel_Table = new JPanel(); 164 | panel_Table.add(table); 165 | 166 | add(panel, BorderLayout.NORTH); 167 | add(panel_Table, BorderLayout.WEST); 168 | add(scrollPane, BorderLayout.CENTER); 169 | Host.JTextAreaOutputStream out = new Host.JTextAreaOutputStream(textArea); 170 | System.setOut(new PrintStream(out));//设置输出重定向 171 | 172 | // 显示窗口 173 | setVisible(true); 174 | } 175 | } 176 | 177 | 178 | public void StartRouter(Router router) throws IOException { 179 | router.SetRouter(); 180 | Socket socket_Between; 181 | //每次启动都清空路由器的ARP表 182 | if(Router_Sym == 'I'){ 183 | clearFile("src/Processes/I_ARP_Table.ser"); 184 | Socket_Ex = new Socket("localhost", 9998); 185 | socket_Between = new Socket("localhost", 8888); 186 | } 187 | else { 188 | clearFile("src/Processes/J_ARP_Table.ser"); 189 | Socket_Ex = new Socket("localhost", 9997); 190 | socket_Between = new Socket("localhost", 8888); 191 | } 192 | router.HandShake(); 193 | final PipedOutputStream output = new PipedOutputStream(); 194 | final PipedInputStream input = new PipedInputStream(output); 195 | new RouterReadServer(Socket_Ex, socket_Between, input, output, 1).start(); 196 | new RouterReadServer(Socket_Ex, socket_Between, input, output, 2).start(); 197 | new RouterReadPipe(Socket_Ex, socket_Between , input, output).start(); 198 | } 199 | 200 | public static void main(String[] args) throws IOException { 201 | Router router = new Router(); 202 | new MyWindow(router); 203 | } 204 | } 205 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /src/Processes/RouterReadPipe.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import java.io.*; 3 | import java.net.Socket; 4 | import java.util.*; 5 | 6 | import static Processes.AppendKeyValuePairToFile.readHashMapFromFile; 7 | import static Processes.Host.*; 8 | import static Processes.Router.Interface_E0_IP; 9 | import static Processes.Router.Router_Sym; 10 | import static Processes.SwitcherMultiThreadProcess.byte2ToInt; 11 | import static Processes.SwitcherMultiThreadProcess.byteArrayToIp; 12 | import static Processes.Table.Sym_IP_Table; 13 | 14 | public class RouterReadPipe extends Thread { 15 | private static Socket socket_EX; 16 | private static Socket socket_Between; 17 | private static PipedInputStream input; 18 | private static final int bufferSize = 8092; 19 | private static PipedOutputStream output; 20 | 21 | public RouterReadPipe(Socket socket_ex, Socket socket_between, PipedInputStream input1 , PipedOutputStream output1) { 22 | socket_EX = socket_ex; 23 | socket_Between = socket_between; 24 | input = input1; 25 | output = output1; 26 | } 27 | 28 | public void Transit_Server(Socket socket, byte[] by, int res) 29 | { 30 | // 将服务器接收到的消息发送给除了发送方以外的其他客户端 31 | BufferedOutputStream ps = null; 32 | try { 33 | ps = new BufferedOutputStream(socket.getOutputStream()); 34 | ps.write(by, 0, res); // 写入输出流,将内容发送给客户端的输入流 35 | ps.flush(); 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | public char GetSrcIP_Sym(String Source_IP_Str){ 42 | char sym = 0; 43 | for(char getKey: Sym_IP_Table.keySet()){ 44 | if(Sym_IP_Table.get(getKey).equals(Source_IP_Str)){ 45 | sym = getKey; 46 | } 47 | } 48 | return sym; 49 | } 50 | 51 | 52 | @Override 53 | public void run() { 54 | try { 55 | int i = 0; 56 | while(true){ 57 | byte[] by = new byte[bufferSize]; 58 | int res = 0; 59 | res = input.read(by); 60 | if(by[0] == by[1] && by[1] == by[2] && by[2] == by[3] && by[0] == 0) 61 | by[0] = 4; 62 | byte Frame_Type = by[0]; 63 | String Mac_I_E0 = "17-10-22-ED-87-78"; 64 | String Mac_I_E1 = "18-10-22-ED-87-78"; 65 | String Mac_J_E0 = "19-10-22-ED-87-78"; 66 | String Mac_J_E1 = "20-10-22-ED-87-78"; 67 | byte[] byte_Mac_I_E0 = MacToByte(Mac_I_E0); 68 | byte[] byte_Mac_I_E1 = MacToByte(Mac_I_E1); 69 | byte[] byte_Mac_J_E0 = MacToByte(Mac_J_E0); 70 | byte[] byte_Mac_J_E1 = MacToByte(Mac_J_E1); 71 | if(Frame_Type == 0) { 72 | byte[] Dest_Mac = Arrays.copyOfRange(by, 1, 7); 73 | byte[] Src_Mac = Arrays.copyOfRange(by, 7, 13); 74 | byte[] Dest_IP = Arrays.copyOfRange(by, 13, 17); 75 | byte[] Src_IP = Arrays.copyOfRange(by, 17, 21); 76 | byte[] Data_length = Arrays.copyOfRange(by, 21, 23); 77 | int Data_length_int = byte2ToInt(Data_length, 0); 78 | byte[] Data = Arrays.copyOfRange(by, 23, 23 + Data_length_int); 79 | String Data_str = new String(Data); 80 | String Dest_Mac_str = byteToMac(Dest_Mac); 81 | String Src_Mac_str = byteToMac(Src_Mac); 82 | String Dest_IP_str = byteArrayToIp(Dest_IP); 83 | String Src_IP_str = byteArrayToIp(Src_IP); 84 | // System.out.println("获取到报文类型为:数据报文,\n目的MAC地址为" + Dest_Mac_str + ",源MAC地址为" + Src_Mac_str + ",\n目的IP地址为" + Dest_IP_str + ",源IP地址为" + Src_IP_str + ",\n数据长度为" + Data_length_int + ",数据为" + Data_str); 85 | char sym = GetSrcIP_Sym(Src_IP_str); 86 | if (((sym == 'A' || sym == 'B' || sym == 'C') && Router_Sym == 'I') || 87 | ((sym == 'D' || sym == 'F') && Router_Sym == 'J')) { 88 | int finalRes1 = res; 89 | new Thread(() -> { 90 | Transit_Server(socket_Between, by, finalRes1); 91 | }).start(); 92 | } else { 93 | char Dest_Sym = GetSrcIP_Sym(Dest_IP_str); 94 | if (Dest_Sym == 'A' || Dest_Sym == 'B' || Dest_Sym == 'C') { 95 | for (int j = 1; j < 7; j++) { 96 | by[j + 6] = by[j]; 97 | by[j] = byte_Mac_I_E0[j - 1]; 98 | Src_Mac_str = Mac_I_E0; 99 | Src_IP_str = Interface_E0_IP; 100 | } 101 | } else if (Dest_Sym == 'D' || Dest_Sym == 'F') { 102 | for (int j = 1; j < 7; j++) { 103 | by[j + 6] = by[j]; 104 | by[j] = byte_Mac_J_E0[j - 1]; 105 | Src_Mac_str = Mac_J_E0; 106 | Src_IP_str = Interface_E0_IP; 107 | } 108 | } 109 | String file_path; 110 | System.out.println(Dest_IP_str); 111 | if (Router_Sym == 'I') { 112 | file_path = "src/Processes/I_ARP_Table.ser"; 113 | } else { 114 | file_path = "src/Processes/J_ARP_Table.ser"; 115 | } 116 | if (!readHashMapFromFile(file_path).containsKey(Dest_IP_str)) { 117 | System.out.println("ARP高速缓存中没有下一跳地址,正在发送ARP请求报文..."); 118 | String finalSrc_Mac_str = Src_Mac_str; 119 | String finalSrc_IP_str = Src_IP_str; 120 | new Thread(() -> { 121 | try { 122 | SendARPRequest(Dest_IP_str, socket_EX, finalSrc_IP_str, finalSrc_Mac_str); 123 | } catch (IOException ex) { 124 | throw new RuntimeException(ex); 125 | } 126 | }).start(); 127 | boolean flag_MAC = false; 128 | while (true) { 129 | // System.out.println("Circle ARP高速缓存中的内容为:"); 130 | // for(String getKey: readHashMapFromFile(file_path).keySet()){ 131 | // System.out.println(getKey + " : " + readHashMapFromFile(file_path).get(getKey)); 132 | // } 133 | for (String getKey : readHashMapFromFile(file_path).keySet()) { 134 | if (getKey.equals(Dest_IP_str)) { 135 | flag_MAC = true; 136 | break; 137 | } 138 | } 139 | if (flag_MAC) 140 | break; 141 | try { 142 | System.out.println("等待ARP响应报文..."); 143 | Thread.sleep(1000); 144 | } catch (InterruptedException e) { 145 | e.printStackTrace(); 146 | } 147 | } 148 | } 149 | int finalRes = res; 150 | System.out.println("正在转发数据报文..."); 151 | new Thread(() -> { 152 | Transit_Server(socket_EX, by, finalRes); 153 | }).start(); 154 | System.out.println("数据报文发送完毕。\n"); 155 | } 156 | } 157 | } 158 | 159 | } catch (IOException e) { 160 | throw new RuntimeException(e); 161 | } 162 | } 163 | 164 | private void SendARPRequest(String Dest_IP, Socket socketEx, String Src_IP, String Src_Mac) throws IOException { 165 | byte[] byte_Dest_IP = ipToByteArray(Dest_IP); 166 | byte[] byte_Source_IP = ipToByteArray(Src_IP); 167 | String Dest_MAC = "00-00-00-00-00-00"; 168 | byte[] byte_Dest_MAC = MacToByte(Dest_MAC); 169 | byte[] byte_Source_MAC = MacToByte(Src_Mac); 170 | 171 | OutputStream outputStream = socketEx.getOutputStream(); 172 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 173 | byte Frame_type = (byte) 1; 174 | dataOutputStream.write(Frame_type); 175 | dataOutputStream.write(byte_Dest_MAC); 176 | dataOutputStream.write(byte_Source_MAC); 177 | dataOutputStream.write(byte_Dest_IP); 178 | dataOutputStream.write(byte_Source_IP); 179 | dataOutputStream.flush(); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/Processes/RouterReadServer.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import java.io.*; 3 | import java.net.Socket; 4 | import java.util.*; 5 | 6 | import static Processes.AppendKeyValuePairToFile.appendKeyValuePairToFile; 7 | import static Processes.AppendKeyValuePairToFile.readHashMapFromFile; 8 | import static Processes.Host.MacToByte; 9 | import static Processes.Host.byteToMac; 10 | import static Processes.Router.*; 11 | import static Processes.SwitcherMultiThreadProcess.byte2ToInt; 12 | import static Processes.SwitcherMultiThreadProcess.byteArrayToIp; 13 | import static Processes.Table.Sym_IP_Table; 14 | 15 | public class RouterReadServer extends Thread { 16 | private static Socket socket; 17 | private static Socket socket_EX; 18 | private static Socket socket_Between; 19 | private static final int bufferSize = 8092; 20 | private static PipedInputStream input; 21 | private static PipedOutputStream output; 22 | private int Flag; 23 | private String IP_Str; 24 | private String Mac_Str; 25 | 26 | public RouterReadServer(Socket socket_ex, Socket socket_between , PipedInputStream input1 , PipedOutputStream output1, int flag) { 27 | socket_EX = socket_ex; 28 | socket_Between = socket_between; 29 | input = input1; 30 | output = output1; 31 | Flag = flag; 32 | if(Router_Sym == 'I' && Flag == 1){ 33 | IP_Str = Interface_E0_IP; 34 | Mac_Str = Interface_E0_MAC; 35 | } 36 | else if(Router_Sym == 'I' && Flag == 2){ 37 | IP_Str = Interface_E1_IP; 38 | Mac_Str = Interface_E1_MAC; 39 | } 40 | else if(Router_Sym == 'J' && Flag == 1){ 41 | IP_Str = Interface_E0_IP; 42 | Mac_Str = Interface_E0_MAC; 43 | } 44 | else if(Router_Sym == 'J' && Flag == 2){ 45 | IP_Str = Interface_E1_IP; 46 | Mac_Str = Interface_E1_MAC; 47 | } 48 | } 49 | 50 | public void Transit_Pipe(byte[] by, int res) 51 | { 52 | // 将服务器接收到的消息发送给除了发送方以外的其他客户端 53 | try { 54 | output.write(by, 0, res); // 写入输出流,将内容发送给客户端的输入流 55 | output.flush(); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | 61 | public char GetSrcIP_Sym(String Source_IP_Str){ 62 | char sym = 0; 63 | for(char getKey: Sym_IP_Table.keySet()){ 64 | if(Sym_IP_Table.get(getKey).equals(Source_IP_Str)){ 65 | sym = getKey; 66 | } 67 | } 68 | return sym; 69 | } 70 | 71 | private void SendARPReply(String Dest_Mac_Str, String Src_Mac_Str, String Dest_IP_Str, String Src_IP_Str) throws IOException { 72 | byte[] byte_Dest_MAC = MacToByte(Dest_Mac_Str); 73 | byte[] byte_Source_MAC = MacToByte(Src_Mac_Str); 74 | byte[] byte_Dest_IP = ipToByteArray(Dest_IP_Str); 75 | byte[] byte_Source_IP = ipToByteArray(Src_IP_Str); 76 | 77 | OutputStream outputStream = socket_EX.getOutputStream(); 78 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 79 | byte Frame_type = (byte) 2; 80 | dataOutputStream.write(Frame_type); 81 | dataOutputStream.write(byte_Dest_MAC); 82 | dataOutputStream.write(byte_Source_MAC); 83 | dataOutputStream.write(byte_Dest_IP); 84 | dataOutputStream.write(byte_Source_IP); 85 | dataOutputStream.flush(); 86 | } 87 | 88 | @Override 89 | public void run() { 90 | // System.out.println(Mac_Str); 91 | BufferedInputStream ois = null; 92 | BufferedOutputStream oos = null; 93 | if(Flag == 1) 94 | socket = socket_EX; 95 | else 96 | socket = socket_Between; 97 | try { 98 | ois = new BufferedInputStream(socket.getInputStream()); 99 | oos = new BufferedOutputStream(socket.getOutputStream()); 100 | int i = 0; 101 | while(true){ 102 | byte[] by = new byte[bufferSize]; 103 | int res = 0; 104 | res = ois.read(by); 105 | if(by[0] == by[1] && by[1] == by[2] && by[2] == by[3] && by[0] == 0) 106 | by[0] = 4; 107 | byte Frame_Type = by[0]; 108 | if(Frame_Type == 0){ 109 | String Mac_I_E0 = "17-10-22-ED-87-78"; 110 | String Mac_I_E1 = "18-10-22-ED-87-78"; 111 | String Mac_J_E0 = "19-10-22-ED-87-78"; 112 | String Mac_J_E1 = "20-10-22-ED-87-78"; 113 | byte[] byte_Mac_I_E0 = MacToByte(Mac_I_E0); 114 | byte[] byte_Mac_I_E1 = MacToByte(Mac_I_E1); 115 | byte[] byte_Mac_J_E0 = MacToByte(Mac_J_E0); 116 | byte[] byte_Mac_J_E1 = MacToByte(Mac_J_E1); 117 | byte[] Dest_Mac = Arrays.copyOfRange(by, 1, 7); 118 | byte[] Src_Mac = Arrays.copyOfRange(by, 7, 13); 119 | byte[] Dest_IP = Arrays.copyOfRange(by, 13, 17); 120 | byte[] Src_IP = Arrays.copyOfRange(by, 17, 21); 121 | byte[] Data_length = Arrays.copyOfRange(by, 21, 23); 122 | int Data_length_int = byte2ToInt(Data_length, 0); 123 | byte[] Data = Arrays.copyOfRange(by, 23, 23 + Data_length_int); 124 | String Data_str = new String(Data); 125 | String Dest_Mac_str = byteToMac(Dest_Mac); 126 | String Src_Mac_str = byteToMac(Src_Mac); 127 | String Dest_IP_str = byteArrayToIp(Dest_IP); 128 | String Src_IP_str = byteArrayToIp(Src_IP); 129 | System.out.println("获取到报文类型为:数据报文,\n目的MAC地址为" + Dest_Mac_str + ",源MAC地址为" + Src_Mac_str + ",\n目的IP地址为" + Dest_IP_str + ",源IP地址为" + Src_IP_str + ",\n数据长度为" + Data_length_int + ",数据为" + Data_str + "\n"); 130 | if(Router_Sym == 'I'){ 131 | if(!readHashMapFromFile("src/Processes/I_ARP_Table.ser").containsKey(Interface_E1_IP)){ 132 | //将路由器J的E1端口信息添加到ARP高速缓存中 133 | appendKeyValuePairToFile("202.119.66.101", "20-10-22-ED-87-78", "src/Processes/I_ARP_Table.ser"); 134 | myWindow.addData("202.119.66.101", "20-10-22-ED-87-78"); 135 | } 136 | } 137 | else{ 138 | if(!readHashMapFromFile("src/Processes/J_ARP_Table.ser").containsKey(Interface_E1_IP)){ 139 | //将路由器I的E1端口信息添加到ARP高速缓存中 140 | appendKeyValuePairToFile("202.119.66.100", "18-10-22-ED-87-78", "src/Processes/J_ARP_Table.ser"); 141 | myWindow.addData("202.119.66.100", "18-10-22-ED-87-78"); 142 | } 143 | } 144 | 145 | char sym = GetSrcIP_Sym(Src_IP_str); 146 | if(((Flag == 1) && (socket_EX.getPort() == 9998) && (sym == 'A' || sym == 'B' || sym == 'C'))){ 147 | for(int j = 1; j < 7; j++){ 148 | by[j + 6] = by[j]; 149 | by[j] = byte_Mac_I_E1[j - 1]; 150 | } 151 | } 152 | else if(((Flag == 1) && (socket_EX.getPort() == 9997) && (sym == 'D' || sym == 'F'))){ 153 | for(int j = 1; j < 7; j++){ 154 | by[j + 6] = by[j]; 155 | by[j] = byte_Mac_J_E1[j - 1]; 156 | } 157 | } 158 | else if(Flag == 2){ 159 | if(socket_EX.getPort() == 9998){ 160 | // System.out.println("9998"); 161 | for(int j = 1; j < 7; j++){ 162 | by[j + 6] = by[j]; 163 | by[j] = byte_Mac_I_E1[j - 1]; 164 | } 165 | } 166 | else{ 167 | // System.out.println("9997"); 168 | for(int j = 1; j < 7; j++){ 169 | by[j + 6] = by[j]; 170 | by[j] = byte_Mac_J_E1[j - 1]; 171 | } 172 | } 173 | } 174 | Transit_Pipe(by, res); 175 | } 176 | 177 | else if (Frame_Type == 1) { 178 | byte[] Dest_Mac = Arrays.copyOfRange(by, 1, 7); 179 | byte[] Src_Mac = Arrays.copyOfRange(by, 7, 13); 180 | byte[] Dest_IP = Arrays.copyOfRange(by, 13, 17); 181 | byte[] Src_IP = Arrays.copyOfRange(by, 17, 21); 182 | // String Dest_Mac_str = byteToMac(Dest_Mac); 183 | String Src_Mac_str = byteToMac(Src_Mac); 184 | String Dest_IP_str = byteArrayToIp(Dest_IP); 185 | String Src_IP_str = byteArrayToIp(Src_IP); 186 | String Dest_Mac_str = Interface_E0_MAC; 187 | if(Dest_IP_str.equals(Interface_E0_IP)){ 188 | System.out.println("获取到报文类型为:ARP请求报文,\n目的MAC地址为" + Dest_Mac_str + ",源MAC地址为" + Src_Mac_str + ",\n目的IP地址为" + Dest_IP_str + ",源IP地址为" + Src_IP_str + "\n"); 189 | if(Router_Sym == 'I'){ 190 | if(!readHashMapFromFile("src/Processes/I_ARP_Table.ser").containsKey(Src_IP_str)){ 191 | appendKeyValuePairToFile(Src_IP_str, Src_Mac_str, "src/Processes/I_ARP_Table.ser"); 192 | myWindow.addData(Src_IP_str, Src_Mac_str); 193 | } 194 | } 195 | else{ 196 | if(!readHashMapFromFile("src/Processes/J_ARP_Table.ser").containsKey(Src_IP_str)){ 197 | appendKeyValuePairToFile(Src_IP_str, Src_Mac_str, "src/Processes/J_ARP_Table.ser"); 198 | myWindow.addData(Src_IP_str, Src_Mac_str); 199 | } 200 | } 201 | new Thread(()->{ 202 | try { 203 | SendARPReply(Src_Mac_str, Dest_Mac_str, Src_IP_str, Dest_IP_str); 204 | } catch (IOException ex) { 205 | throw new RuntimeException(ex); 206 | } 207 | }).start(); 208 | } 209 | 210 | } 211 | else if (Frame_Type == 2) 212 | { 213 | byte[] Dest_Mac = Arrays.copyOfRange(by, 1, 7); 214 | byte[] Src_Mac = Arrays.copyOfRange(by, 7, 13); 215 | byte[] Dest_IP = Arrays.copyOfRange(by, 13, 17); 216 | byte[] Src_IP = Arrays.copyOfRange(by, 17, 21); 217 | String Dest_Mac_str = byteToMac(Dest_Mac); 218 | String Src_Mac_str = byteToMac(Src_Mac); 219 | String Dest_IP_str = byteArrayToIp(Dest_IP); 220 | String Src_IP_str = byteArrayToIp(Src_IP); 221 | if(Dest_IP_str.equals(Interface_E0_IP)){ 222 | System.out.println("获取到报文类型为:ARP响应报文,\n目的MAC地址为" + Dest_Mac_str + ",源MAC地址为" + Src_Mac_str + ",\n目的IP地址为" + Dest_IP_str + ",源IP地址为" + Src_IP_str + "\n"); 223 | if(Router_Sym == 'I'){ 224 | appendKeyValuePairToFile(Src_IP_str, Src_Mac_str, "src/Processes/I_ARP_Table.ser"); 225 | myWindow.addData(Src_IP_str, Src_Mac_str); 226 | 227 | } 228 | else{ 229 | appendKeyValuePairToFile(Src_IP_str, Src_Mac_str, "src/Processes/J_ARP_Table.ser"); 230 | myWindow.addData(Src_IP_str, Src_Mac_str); 231 | } 232 | 233 | } 234 | 235 | } 236 | } 237 | 238 | } catch (IOException e) { 239 | throw new RuntimeException(e); 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/Processes/RouterTrans.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import java.io.*; 3 | import java.net.ServerSocket; 4 | import java.net.Socket; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | 9 | public class RouterTrans { 10 | private ServerSocket Transit_Socket; 11 | private static final int bufferSize = 8092; 12 | private List listSockets = new ArrayList<>(); 13 | private int i = 0; 14 | 15 | public static String byteArrayToIp(byte[] bs) { 16 | StringBuilder sb = new StringBuilder(); 17 | for (int i=0 ; i < bs.length; i++) { 18 | if(i != bs.length - 1){ 19 | sb.append(bs[i] & 0xff).append("."); 20 | }else{ 21 | sb.append(bs[i] & 0xff); 22 | } 23 | } 24 | return sb.toString(); 25 | } 26 | 27 | public void BroadCast(Socket socket_now, byte[] by, int res) 28 | { 29 | // 将服务器接收到的消息发送给除了发送方以外的其他客户端 30 | for (Socket socket: listSockets) 31 | { 32 | if (socket != socket_now) // 判断不是当前发送的客户端 33 | { 34 | BufferedOutputStream ps = null; 35 | try { 36 | ps = new BufferedOutputStream(socket.getOutputStream()); 37 | ps.write(by, 0, res); // 写入输出流,将内容发送给客户端的输入流 38 | ps.flush(); 39 | } catch (IOException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | } 44 | } 45 | 46 | private void Transit_Between(Integer port) throws IOException { 47 | Transit_Socket =new ServerSocket(port); 48 | while (true){ 49 | //等待客户端的连接 50 | Socket socket_now = Transit_Socket.accept(); 51 | listSockets.add(socket_now); 52 | System.out.println(listSockets.get(i)); 53 | i++; 54 | //每当有一个客户端连接进来后,就启动一个单独的线程进行处理 55 | new Thread(new Runnable() { 56 | @Override 57 | public void run() { 58 | //获取输入流,并且指定统一的编码格式 59 | BufferedInputStream ois = null; 60 | BufferedOutputStream oos = null; 61 | try { 62 | ois = new BufferedInputStream(socket_now.getInputStream()); 63 | oos = new BufferedOutputStream(socket_now.getOutputStream()); 64 | while(true){ 65 | byte[] by = new byte[bufferSize]; 66 | int res = 0; 67 | res = ois.read(by); 68 | if(res <= 0) 69 | res = 0; 70 | BroadCast(socket_now, by, res); 71 | } 72 | }catch (IOException e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | }).start(); 77 | } 78 | } 79 | 80 | public static void main(String[] args) throws IOException { 81 | RouterTrans server = new RouterTrans(); 82 | server.Transit_Between(8888); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/Processes/Switcher.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import javax.swing.*; 3 | import java.awt.*; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.io.*; 7 | import java.net.ServerSocket; 8 | import java.net.Socket; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Scanner; 13 | 14 | import static Processes.FileOperation.clearFile; 15 | 16 | public class Switcher { 17 | public static char Switcher_Sym; 18 | private String Router_IP; 19 | private Integer Router_Port; 20 | private String Switcher_IP; 21 | private Integer Switcher_Port; 22 | private ServerSocket Switcher_Socket; 23 | private List listSocket = new ArrayList<>(); 24 | public static volatile HashMap Switcher_Table = new HashMap<>(); //交换机站表:接口号-源MAC地址 25 | public Switcher() { 26 | } 27 | 28 | public static String byteArrayToIp(byte[] bs) { 29 | StringBuilder sb = new StringBuilder(); 30 | for (int i=0 ; i < bs.length; i++) { 31 | if(i != bs.length - 1){ 32 | sb.append(bs[i] & 0xff).append("."); 33 | }else{ 34 | sb.append(bs[i] & 0xff); 35 | } 36 | } 37 | return sb.toString(); 38 | } 39 | 40 | public static class MyWindow extends JFrame { 41 | private final JComboBox comboBox; 42 | private final JTextArea textArea; 43 | 44 | public MyWindow(Switcher switcher) { 45 | JFrame.setDefaultLookAndFeelDecorated(true); 46 | // 设置窗口属性 47 | setTitle("交换机"); 48 | setSize(400, 300); 49 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 50 | setLocationRelativeTo(null); 51 | 52 | // 创建下拉框 53 | String[] options = {"M", "N"}; 54 | comboBox = new JComboBox<>(options); 55 | 56 | // 创建按钮 57 | JButton button = new JButton("启动交换机"); 58 | button.addActionListener(new ActionListener() { 59 | @Override 60 | public void actionPerformed(ActionEvent e) { 61 | String option = (String) comboBox.getSelectedItem(); 62 | // 在文本框中显示结果 63 | // textArea.append("Option selected: " + option + "\n"); 64 | Switcher_Sym = option.charAt(0); 65 | new Thread(()->{ 66 | try { 67 | System.out.println("交换机" + Switcher_Sym + "开始运行..."); 68 | switcher.start(); 69 | } catch (IOException ex) { 70 | throw new RuntimeException(ex); 71 | } 72 | }).start(); 73 | } 74 | }); 75 | 76 | 77 | 78 | // 创建文本框 79 | textArea = new JTextArea(10, 30); 80 | textArea.setEditable(false); 81 | JScrollPane scrollPane = new JScrollPane(textArea); 82 | JLabel label_Choose_Switcher = new JLabel("请选择要启动的交换机:"); 83 | 84 | // 添加组件到窗口 85 | JPanel panel = new JPanel(); 86 | panel.add(label_Choose_Switcher); 87 | panel.add(comboBox); 88 | panel.add(button); 89 | 90 | add(panel, BorderLayout.NORTH); 91 | add(scrollPane, BorderLayout.CENTER); 92 | Host.JTextAreaOutputStream out = new Host.JTextAreaOutputStream(textArea); 93 | System.setOut(new PrintStream(out));//设置输出重定向 94 | 95 | // 显示窗口 96 | setVisible(true); 97 | } 98 | } 99 | 100 | 101 | 102 | 103 | 104 | static class JTextAreaOutputStream extends OutputStream 105 | { 106 | private final JTextArea destination; 107 | public JTextAreaOutputStream (JTextArea destination) 108 | { 109 | if (destination == null) 110 | throw new IllegalArgumentException ("Destination is null"); 111 | this.destination = destination; 112 | } 113 | @Override 114 | public void write(byte[] buffer, int offset, int length) throws IOException 115 | { 116 | final String text = new String (buffer, offset, length); 117 | SwingUtilities.invokeLater(new Runnable () 118 | { 119 | @Override 120 | public void run() 121 | { 122 | destination.append (text); 123 | } 124 | }); 125 | } 126 | @Override 127 | public void write(int b) throws IOException 128 | { 129 | write (new byte [] {(byte)b}, 0, 1); 130 | } 131 | } 132 | 133 | public void start() throws IOException { 134 | Switcher switcher = new Switcher(); 135 | 136 | if(Switcher_Sym == 'M'){ 137 | switcher.Switcher_Socket = new ServerSocket(9998); 138 | clearFile("src/Processes/MTable.ser"); 139 | } 140 | else { 141 | switcher.Switcher_Socket = new ServerSocket(9997); 142 | clearFile("src/Processes/NTable.ser"); 143 | } 144 | 145 | 146 | int i = 0; 147 | while(true){ 148 | System.out.println("Waiting for the client to connect..."); 149 | Socket now_socket = switcher.Switcher_Socket.accept(); 150 | switcher.listSocket.add(now_socket); 151 | // System.out.println(switcher.listSocket); 152 | i++; 153 | new SwitcherMultiThreadProcess(now_socket, switcher.listSocket).start(); 154 | } 155 | } 156 | 157 | 158 | 159 | 160 | public static void main(String[] args) throws IOException { 161 | Switcher switcher = new Switcher(); 162 | MyWindow window = new MyWindow(switcher); 163 | 164 | 165 | } 166 | } 167 | 168 | 169 | -------------------------------------------------------------------------------- /src/Processes/SwitcherMultiThreadProcess.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | import java.io.*; 3 | import java.net.Socket; 4 | import java.util.*; 5 | 6 | import static Processes.AppendKeyValuePairToFile.appendKeyValuePairToFile; 7 | import static Processes.AppendKeyValuePairToFile.readHashMapFromFile; 8 | import static Processes.Host.MacToByte; 9 | import static Processes.Host.byteToMac; 10 | import static Processes.Table.Sym_IP_Table; 11 | 12 | public class SwitcherMultiThreadProcess extends Thread{ 13 | private final Socket socket; 14 | private List listSockets = new ArrayList<>(); 15 | private static final int bufferSize = 8092; 16 | private static HashMapInterface_Socket = new HashMap<>(); 17 | 18 | 19 | public SwitcherMultiThreadProcess(Socket socket, List listSockets){ 20 | this.listSockets = listSockets; 21 | this.socket = socket; 22 | } 23 | 24 | public void BroadCast(Socket socket_now, byte[] by, int res) 25 | { 26 | // 将服务器接收到的消息发送给除了发送方以外的其他客户端 27 | for (Socket socket: listSockets) 28 | { 29 | if (socket != socket_now) // 判断不是当前发送的客户端 30 | { 31 | BufferedOutputStream ps = null; 32 | try { 33 | ps = new BufferedOutputStream(socket.getOutputStream()); 34 | ps.write(by, 0, res); // 写入输出流,将内容发送给客户端的输入流 35 | ps.flush(); 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | } 41 | } 42 | 43 | public void TransitTo(Socket socket_sender, byte[] by, int res) 44 | { 45 | BufferedOutputStream ps = null; 46 | try { 47 | ps = new BufferedOutputStream(socket_sender.getOutputStream()); 48 | ps.write(by, 0, res); // 写入输出流,将内容发送给客户端的输入流 49 | ps.flush(); 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | 55 | //change the byte array to IP address 56 | public static String byteArrayToIp(byte[] bs) { 57 | StringBuilder sb = new StringBuilder(); 58 | for (int i=0 ; i < bs.length; i++) { 59 | if(i != bs.length - 1){ 60 | sb.append(bs[i] & 0xff).append("."); 61 | }else{ 62 | sb.append(bs[i] & 0xff); 63 | } 64 | } 65 | return sb.toString(); 66 | } 67 | 68 | public static int byte2ToInt(byte[] bytes, int off) { 69 | int b0 = bytes[off] & 0xFF; 70 | int b1 = bytes[off + 1] & 0xFF; 71 | return (b0 << 8) | b1; 72 | } 73 | 74 | public char GetIP_Sym(String IP_Str){ 75 | char sym = 0; 76 | for(char getKey: Sym_IP_Table.keySet()){ 77 | if(Sym_IP_Table.get(getKey).equals(IP_Str)){ 78 | sym = getKey; 79 | } 80 | } 81 | return sym; 82 | } 83 | 84 | public String Get_Mac_Interface(String Interface, char Switcher_Sym){ 85 | if(Switcher_Sym == 'M'){ 86 | return readHashMapFromFile("src/Processes/MTable.ser").get(Interface); 87 | } 88 | else { 89 | return readHashMapFromFile("src/Processes/NTable.ser").get(Interface); 90 | } 91 | } 92 | 93 | @Override 94 | public void run(){ 95 | BufferedInputStream ois = null; 96 | BufferedOutputStream oos = null; 97 | try { 98 | ois = new BufferedInputStream(socket.getInputStream()); 99 | oos = new BufferedOutputStream(socket.getOutputStream()); 100 | while(true){ 101 | byte[] by = new byte[bufferSize]; 102 | int res = 0; 103 | res = ois.read(by); 104 | if(by[0] == by[1] && by[1] == by[2] && by[2] == by[3] && by[0] == 0) 105 | by[0] = 4; 106 | byte Frame_Type = by[0]; 107 | if(Frame_Type == 0){ 108 | byte[] Dest_Mac = Arrays.copyOfRange(by, 1, 7); 109 | byte[] Src_Mac = Arrays.copyOfRange(by, 7, 13); 110 | byte[] Dest_IP = Arrays.copyOfRange(by, 13, 17); 111 | byte[] Src_IP = Arrays.copyOfRange(by, 17, 21); 112 | byte[] Data_length = Arrays.copyOfRange(by, 21, 23); 113 | int Data_length_int = byte2ToInt(Data_length, 0); 114 | byte[] Data = Arrays.copyOfRange(by, 23, 23 + Data_length_int); 115 | String Data_str = new String(Data); 116 | String Dest_Mac_str = byteToMac(Dest_Mac); 117 | String Src_Mac_str = byteToMac(Src_Mac); 118 | String Dest_IP_str = byteArrayToIp(Dest_IP); 119 | String Src_IP_str = byteArrayToIp(Src_IP); 120 | 121 | //动态更新数据报发送过程中的源MAC地址和目的MAC地址 122 | String byte_src_mac_1 = Integer.toHexString(0xFF & Src_Mac[0]); 123 | String byte_dest_mac_1 = Integer.toHexString(0xFF & Dest_Mac[0]); 124 | int src_mac_1 = Integer.parseInt(byte_src_mac_1); 125 | int dest_mac_1 = Integer.parseInt(byte_dest_mac_1); 126 | String Interface = null; 127 | char Switcher_sym = 0; 128 | if((src_mac_1 == 20 && dest_mac_1 == 19)){ 129 | Switcher_sym = 'N'; 130 | char dest_sym = GetIP_Sym(Dest_IP_str); 131 | if(dest_sym == 'D'){ 132 | Interface = "E0"; 133 | } 134 | else if(dest_sym == 'F'){ 135 | Interface = "E1"; 136 | } 137 | String new_src_mac = Get_Mac_Interface(Interface, Switcher_sym); 138 | byte[] new_src_mac_byte = MacToByte(new_src_mac); 139 | for(int j = 1; j < 7; j++){ 140 | by[j + 6] = by[j]; 141 | by[j] = new_src_mac_byte[j - 1]; 142 | } 143 | } 144 | else if(src_mac_1 == 18 && dest_mac_1 == 17){ 145 | Switcher_sym = 'M'; 146 | char dest_sym = GetIP_Sym(Dest_IP_str); 147 | if(dest_sym == 'A'){ 148 | Interface = "E0"; 149 | } 150 | else if(dest_sym == 'B'){ 151 | Interface = "E1"; 152 | } 153 | else if(dest_sym == 'C'){ 154 | Interface = "E2"; 155 | } 156 | String new_src_mac = Get_Mac_Interface(Interface, Switcher_sym); 157 | byte[] new_src_mac_byte = MacToByte(new_src_mac); 158 | for(int j = 1; j < 7; j++){ 159 | by[j + 6] = by[j]; 160 | by[j] = new_src_mac_byte[j - 1]; 161 | } 162 | } 163 | 164 | //将数据报文直接传给目的主机 165 | else if(src_mac_1 == 11 || src_mac_1 == 12 || src_mac_1 == 13){ 166 | Switcher_sym = 'M'; 167 | for(String getKey: readHashMapFromFile("src/Processes/MTable.ser").keySet()){ 168 | if(Objects.equals(readHashMapFromFile("src/Processes/MTable.ser").get(getKey), Dest_Mac_str)){ 169 | Interface = getKey; 170 | } 171 | } 172 | } 173 | else if(src_mac_1 == 14 || src_mac_1 == 16){ 174 | Switcher_sym = 'N'; 175 | for(String getKey: readHashMapFromFile("src/Processes/NTable.ser").keySet()){ 176 | if(Objects.equals(readHashMapFromFile("src/Processes/NTable.ser").get(getKey), Dest_Mac_str)){ 177 | Interface = getKey; 178 | } 179 | } 180 | } 181 | System.out.println("获取到报文类型为:数据报文,\n目的MAC地址为" + Dest_Mac_str + ",源MAC地址为" + Src_Mac_str + ",\n目的IP地址为" + Dest_IP_str + ",源IP地址为" + Src_IP_str + ",\n数据长度为" + Data_length_int + ",数据为" + Data_str + "\n"); 182 | Socket Sender_Socket = Interface_Socket.get(Interface); 183 | System.out.println("向 " + Interface + " 接口转发数据报文"); 184 | 185 | TransitTo(Sender_Socket, by, res); 186 | } 187 | else if (Frame_Type == 1) { 188 | byte[] Dest_Mac = Arrays.copyOfRange(by, 1, 7); 189 | byte[] Src_Mac = Arrays.copyOfRange(by, 7, 13); 190 | byte[] Dest_IP = Arrays.copyOfRange(by, 13, 17); 191 | byte[] Src_IP = Arrays.copyOfRange(by, 17, 21); 192 | String Dest_Mac_str = byteToMac(Dest_Mac); 193 | String Src_Mac_str = byteToMac(Src_Mac); 194 | String Dest_IP_str = byteArrayToIp(Dest_IP); 195 | String Src_IP_str = byteArrayToIp(Src_IP); 196 | System.out.println("获取到报文类型为:ARP报文,\n目的MAC地址为" + Dest_Mac_str + ",源MAC地址为" + Src_Mac_str + ",\n目的IP地址为" + Dest_IP_str + ",源IP地址为" + Src_IP_str + "\n"); 197 | BroadCast(socket, by, res); 198 | } 199 | else if (Frame_Type == 2) 200 | { 201 | byte[] Dest_Mac = Arrays.copyOfRange(by, 1, 7); 202 | byte[] Src_Mac = Arrays.copyOfRange(by, 7, 13); 203 | byte[] Dest_IP = Arrays.copyOfRange(by, 13, 17); 204 | byte[] Src_IP = Arrays.copyOfRange(by, 17, 21); 205 | String Dest_Mac_str = byteToMac(Dest_Mac); 206 | String Src_Mac_str = byteToMac(Src_Mac); 207 | String Dest_IP_str = byteArrayToIp(Dest_IP); 208 | String Src_IP_str = byteArrayToIp(Src_IP); 209 | System.out.println("获取到报文类型为:ARP响应报文。"); 210 | System.out.println("目的MAC地址为" + Dest_Mac_str + ",源MAC地址为" + Src_Mac_str + ",\n目的IP地址为" + Dest_IP_str + ",源IP地址为" + Src_IP_str + "\n"); 211 | BroadCast(socket, by, res); 212 | } 213 | else if(Frame_Type == 3) 214 | { 215 | byte[] byte_Interface = Arrays.copyOfRange(by, 1, 3); 216 | byte[] byte_mac = Arrays.copyOfRange(by, 3, 9); 217 | String Interface_sym = new String(byte_Interface); 218 | // String ip_str = byteArrayToIp(byte_ip); 219 | String mac_str = byteToMac(byte_mac); 220 | Interface_Socket.put(Interface_sym, socket); 221 | // System.out.println(Interface_Socket); 222 | System.out.println("获取到报文类型为:握手报文,交换机端口"+ Interface_sym + "握手成功!"); 223 | System.out.println("获取到MAC地址为" + mac_str + "\n"); 224 | if(Switcher.Switcher_Sym == 'M') { 225 | appendKeyValuePairToFile(Interface_sym, mac_str, "src/Processes/MTable.ser"); 226 | } 227 | else if(Switcher.Switcher_Sym == 'N'){ 228 | appendKeyValuePairToFile(Interface_sym, mac_str, "src/Processes/NTable.ser"); 229 | } 230 | // BroadCast(socket, by, res); 231 | } 232 | } 233 | } catch (IOException e) { 234 | throw new RuntimeException(e); 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /src/Processes/Table.java: -------------------------------------------------------------------------------- 1 | package Processes; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Table { 6 | public static HashMap Sym_IP_Table = new HashMap() {{ 7 | put('A', "202.119.64.101"); 8 | put('B', "202.119.64.102"); 9 | put('C', "202.119.64.103"); 10 | put('D', "202.119.65.101"); 11 | put('F', "202.119.65.103"); 12 | }}; 13 | 14 | public static HashMap Sym_Mac_Table = new HashMap() {{ 15 | put('A', "11-10-22-ED-87-78"); 16 | put('B', "12-10-22-ED-87-78"); 17 | put('C', "13-10-22-ED-87-78"); 18 | put('D', "14-10-22-ED-87-78"); 19 | put('F', "16-10-22-ED-87-78"); 20 | // put('S', "17-10-22-ED-87-78"); 21 | // put('T', "18-10-22-ED-87-78"); 22 | // put('U', "19-10-22-ED-87-78"); 23 | // put('V', "20-10-22-ED-87-78"); 24 | }}; 25 | } 26 | -------------------------------------------------------------------------------- /src/Processes/map.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/countang/Java_Socket_ARP/fefa3ca1ea8b44c4f4bd559e20b92e58489aa14f/src/Processes/map.ser --------------------------------------------------------------------------------