2017-04-04 73 views
0

我在使用Java中的CRC32庫計算我的校驗和時遇到問題。校驗和一次計算正確,然後在Java中沒有CRC32之後

所以客戶端計算校驗像這樣....

/** 
* Increments current packet message number, selects a 
* random destination, and sends the packet. 
* @param connection 
* @throws InterruptedException 
* @throws IOException 
*/ 
private void generateAndSendPackets(Socket connection) throws InterruptedException, IOException 
{ 
    byte packet[] = new byte[5]; 
    for (byte messageNumber = 0; messageNumber <= 20; messageNumber++) 
    { 
     packet[0] = CLIENT_ID; //SOURCE 
     packet[1] = randomDestination(); //DESTINATION 
     packet[3] = messageNumber; //DATA 
     packet[4] = messageNumber; 
     //Need more data? 
     packet[2] = computeCheckSum(packet); //COMPUTE CHECKSUM 
     send(packet); //SEND PACKET 
     Thread.sleep(4000); //WAIT TO SEND NEXT PACKET 
    } 
    closeConnection(connection); //Closes the connection 
} 

/** 
* Given a packet, it computes the checksum for 
* the packet with internal Checksum library 
* @param packet 
* @return 
*/ 
private byte computeCheckSum(byte[] packet) 
{ 
    Checksum checkSum = new CRC32(); 
    checkSum.update(packet, 0, packet.length); 
    return (byte)checkSum.getValue(); 
} 

然後發送數據包。包括校驗和。

路由器然後計算校驗和是這樣的...

/** 
    * Given a packet, it computes the checksum for 
    * the packet with internal Checksum library 
    * @param p 
    * @return 
    */ 
    private boolean checkCheckSum(byte[] p) 
    { 
     byte[] packet = p; 
     byte[] tempPacket = new byte[5]; 
     tempPacket[0] = packet[0]; 
     tempPacket[1] = packet[1]; 
     tempPacket[3] = packet[3]; 
     tempPacket[4] = packet[4]; 
     Checksum checkSum = new CRC32(); 
     checkSum.update(tempPacket, 0, tempPacket.length); 
     byte cc = (byte)checkSum.getValue(); 
     System.out.println(packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3] + " " + packet[4]); 
     tempPacket[2] = (byte)checkSum.getValue(); 
     System.out.println(tempPacket[0] + " " + tempPacket[1] + " " + tempPacket[2] + " " + tempPacket[3] + " " + tempPacket[4]); 
     if((byte)checkSum.getValue() == packet[2]){ 
      System.out.println(packet[2] + "," + cc); 
      return true; 
     }else{ 
      System.out.println(packet[2] + "," + cc); 
      return false; 
     } 
    } 

所以當它計算和輸出,它不糾正它第一次......不過那之後,只不過沒有像這樣..

Waiting for connection.... 
Connection recieved from /127.0.0.1 on port 9000 
Waiting for packet... 
Packet recieved: 11 44 -118 00 
11 44 -118 0 0 
11 44 -118 0 0 
-118,-118 
<Error here because we weren't done another part yet> 
Waiting for packet... 
Packet recieved: 11 33 -42 11 
11 33 -42 1 1 
11 33 -128 1 1 
-42,-128 
Checksum invalid!!!! 
Waiting for packet... 

然後每個後無效....

所以它得到正確的校驗一次,那之後搞砸了,再次得到檢驗。我認爲這是我做錯了Java的CRC32庫是我的猜測。這些都是他們自己的線索,但我不認爲這會是一個問題。

這是我們下面的代碼,我試圖強調上述問題的部分,因爲有一些地方有這樣完成了一半....

Client.java

package runner; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.util.*; 
import java.util.zip.CRC32; 
import java.util.zip.Checksum; 

/** 
* Client side for our client 
* server project. Sends a request 
* with a string to reverse. 
* @author xxxxx 
* 
*/ 
public class Client 
{ 
    private static final int PORT = 9000; 

    private static final String HOST = "localhost"; 

    private static final byte CLIENT_ID = (byte)11; 

    private Random rand; 

    //For reciving packets 
    private ServerSocket clientRecieverSocket = null; 

    //Output to server 
    private PrintWriter out; 

    //Input from server 
    private Scanner conIn; 

    //Input from user 
    private Scanner in; 

    //Data Output Stream 
    private DataOutputStream dos; 

    /** 
    * Creates a new instance of the client 
    * @param args 
    * @throws UnknownHostException 
    * @throws IOException 
    * @throws InterruptedException 
    */ 
    public static void main(String[] args) throws IOException, InterruptedException 
    { 
     Client c = new Client(); 
     c.run(); 
    } 

    /** 
    * Runs the client 
    * 
    * @throws UnknownHostException 
    * @throws IOException 
    * @throws InterruptedException 
    */ 
    private void run() throws IOException, InterruptedException 
    { 
     String msg; //Recieve messages from server 

     //Opens connection 
     Socket connection = openConnection(); 

     //Gets I/O streams from server 
     System.out.println("Getting output stream..."); 
     out = new PrintWriter(connection.getOutputStream()); 
     System.out.println("Getting input stream..."); 
     conIn = new Scanner(connection.getInputStream()); 
     System.out.println(); 
     dos = new DataOutputStream(connection.getOutputStream()); 
     msg = conIn.nextLine(); 
     System.out.println(msg); 
     in = new Scanner(System.in); 

     generateAndSendPackets(connection); 
    } 

    /** 
    * Increments current packet message number, selects a 
    * random destination, and sends the packet. 
    * @param connection 
    * @throws InterruptedException 
    * @throws IOException 
    */ 
    private void generateAndSendPackets(Socket connection) throws InterruptedException, IOException 
    { 
     byte packet[] = new byte[5]; 
     for (byte messageNumber = 0; messageNumber <= 20; messageNumber++) 
     { 
      packet[0] = CLIENT_ID; //SOURCE 
      packet[1] = randomDestination(); //DESTINATION 
      packet[3] = messageNumber; //DATA 
      packet[4] = messageNumber; 
      //Need more data? 
      packet[2] = computeCheckSum(packet); //COMPUTE CHECKSUM 
      send(packet); //SEND PACKET 
      Thread.sleep(4000); //WAIT TO SEND NEXT PACKET 
     } 
     closeConnection(connection); //Closes the connection 
    } 


    /** 
    * Given a packet, it computes the checksum for 
    * the packet with internal Checksum library 
    * @param packet 
    * @return 
    */ 
    private byte computeCheckSum(byte[] packet) 
    { 
     Checksum checkSum = new CRC32(); 
     checkSum.update(packet, 0, packet.length); 
     return (byte)checkSum.getValue(); 
    } 

    /** 
    * Select random destination 
    * to send to. 
    */ 
    private byte randomDestination() 
    { 
     List<Byte> destinations = Arrays.asList((byte)22,(byte)33,(byte)44); 
     //destinations.remove(CLIENT_ID); //Do not send it to itself... 
     rand = new Random(); 
     return destinations.get(rand.nextInt(destinations.size())); //converts string to byte 
    } 

    /** 
    * Open the connection 
    * @return 
    * @throws UnknownHostException 
    * @throws IOException 
    */ 
    private Socket openConnection() throws IOException 
    { 
     System.out.println("Connecting to server..."); 
     Socket connection = new Socket(HOST, PORT); //Connects to server 
     System.out.println("Connection made!"); 
     return connection; 
    } 

    /** 
    * Closes the connection 
    * @param connection 
    * @throws IOException 
    */ 
    private void closeConnection(Socket connection) throws IOException 
    { 
     System.out.println("Closing connection..."); 
     connection.close(); 
    } 

    /** 
    * Sends a message to the server 
    * with the string to reverse. 
    * @param packet 
    */ 
    private void send(byte[] packet) throws IOException 
    { 
     System.out.println("You sent " + packet + ", sending message..."); 
     System.out.println(packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3] + " " + packet[4]); 
     dos.write(packet, 0, packet.length); 
     dos.flush(); 
    } 
} 

Router.java

import javax.xml.crypto.Data; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.util.Hashtable; 
import java.util.Scanner; 
import java.util.zip.CRC32; 
import java.util.zip.Checksum; 

/** 
* Router class routes messages 
* around to different routers/clients 
* 
* @Author Abe and Carson 
*/ 
public class Router{ 
    //Stores routing table 
    private Hashtable<Byte, String> routingTable; 

    //Stores socket 
    private static ServerSocket SERVER; 

    private static Socket CLIENT; 

    //Stores router ID (CHANGE THIS IS HARDCODED!!!!!!) 
    private static final int ROUTER_ID = 1; 

    public static void main(String args[]) throws IOException 
    { 
     Router r = new Router(); 
     System.out.println("Waiting for connection...."); 
     while(true) 
     { 
      Socket incomingConnection = SERVER.accept(); 
      System.out.println("Connection recieved from " 
        + incomingConnection.getInetAddress() 
        + " on port " 
        + incomingConnection.getLocalPort()); 
      RouterHandlerThread rht = new RouterHandlerThread(incomingConnection, r); 
      rht.start(); 
     } 
    } 

    /** 
    * Creates a router object 
    * with a server socket that opens to listen for packets 
    * and a routing table 
    */ 
    public Router() 
    { 
     //Creates routing tables HashTable<Byte, String> for router to use based on its ID 
     RoutingTableFactory rtf = new RoutingTableFactory(); 
     try{ 
      routingTable = rtf.getRoutingTable(ROUTER_ID); 
     } catch(RoutingTableFactory.InvalidRouterIDException e){ 
      e.printStackTrace(); 
     } 
     try { 
      SERVER = new ServerSocket(9000); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Getter for the routers 
    * Routing Table 
    * @return 
    */ 
    public Hashtable<Byte, String> getRoutingTable() 
    { 
     return this.routingTable; 
    } 

    /** 
    * Thread for handling router processes for 
    * forwarding a packet to a different link. 
    */ 
    private static class RouterHandlerThread extends Thread 
    { 
     private Socket connection; 
     private Router router; 
     private Scanner in; 
     private PrintWriter out; 
     //Used for sending the packet byte[], can't use Scanner for byte[] :(
     private DataInputStream dis; 
     RouterHandlerThread(Socket c, Router r) throws IOException 
     { 
      this.router = r; 
      this.connection = c; 
      in = new Scanner(c.getInputStream()); 
      out = new PrintWriter(c.getOutputStream()); 
      dis = new DataInputStream(c.getInputStream()); 
     } 

     /** 
     * Given a packet, it computes the checksum for 
     * the packet with internal Checksum library 
     * @param p 
     * @return 
     */ 
     private boolean checkCheckSum(byte[] p) 
     { 
      byte[] packet = p; 
      byte[] tempPacket = new byte[5]; 
      tempPacket[0] = packet[0]; 
      tempPacket[1] = packet[1]; 
      tempPacket[3] = packet[3]; 
      tempPacket[4] = packet[4]; 
      Checksum checkSum = new CRC32(); 
      checkSum.update(tempPacket, 0, tempPacket.length); 
      byte cc = (byte)checkSum.getValue(); 
      System.out.println(packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3] + " " + packet[4]); 
      tempPacket[2] = (byte)checkSum.getValue(); 
      System.out.println(tempPacket[0] + " " + tempPacket[1] + " " + tempPacket[2] + " " + tempPacket[3] + " " + tempPacket[4]); 
      if((byte)checkSum.getValue() == packet[2]){ 
       System.out.println(packet[2] + "," + cc); 
       return true; 
      }else{ 
       System.out.println(packet[2] + "," + cc); 
       return false; 
      } 
     } 

     public void run() 
     { 
      out.println("R: Connected to router " + ROUTER_ID + " at " + SERVER.getLocalPort()); 
      out.flush(); 
      while(connection.isConnected()) 
      { 
       byte[] packet = new byte[5]; 
       System.out.println("Waiting for packet..."); 
       //Reads packet byte[] from the client, stores in packet. 
       try{ 
        dis.readFully(packet); 
       }catch(Exception e){ 
        e.printStackTrace(); 
       } 
       //Print out each byte of packet. 
       System.out.println("Packet recieved: " + packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3] + packet[4]); 
       //Get routing table, look up what link to send packet to. 
       Hashtable<Byte, String> routingTable = router.getRoutingTable(); 
       if(checkCheckSum(packet)){ 
        String destination = routingTable.get(packet[1]); 

        try { 
         Socket targetRouter = new Socket(destination, 9000); 
         DataOutputStream dos = new DataOutputStream(targetRouter.getOutputStream()); 
         dos.write(packet); 
         dos.flush(); 
         System.out.println("Forwarding to " + destination); 
         targetRouter.close(); 
         dos.close(); 
        } catch (UnknownHostException e) { 
         e.printStackTrace(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
       }else{ 
        System.out.println("Checksum invalid!!!!"); 
       } 
      } 
     } 
    } 
} 

/********** 
* CODE FIDDLING WITH STRINGS -> BYTES AND VICE VERSA 
public static void main(String[] args) 
{ 
byte packet[] = new byte[4]; 
packet[0] = 'D'; 
packet[1] = 'B'; 
packet[3] = 29; 

Checksum checkSum = new CRC32(); 
checkSum.update(packet, 0, packet.length); 
packet[2] = (byte)checkSum.getValue(); 

System.out.println(packet[0] + " " + packet[1] + " " + packet[2] + " " + packet[3]); 
String str = new String(packet); 
System.out.println(str); 
} 
*/ 
+0

爲什麼使用CRC-32並只傳輸一個字節?這根本不符合邏輯。 – EJP

回答

1

當您計算校驗和時,packet[2]必須設置爲零。在代碼的某個部分,即函數generateAndSendPackets中,您正在重複使用相同的字節[]來發送多個數據包,但是您保留前一個校驗和字節packet[2],導致新的校驗和值不正確。

byte packet[] = new byte[5]; 
    for (byte messageNumber = 0; messageNumber <= 20; messageNumber++) 
    { 
     packet[0] = CLIENT_ID; //SOURCE 
     packet[1] = randomDestination(); //DESTINATION 
     packet[3] = messageNumber; //DATA 
     packet[4] = messageNumber; 
     //Need more data? 

     // ******************** 
     packet[2] = (byte) 0; // <<<<<< You have to set it to zero 
     // ******************** 

     packet[2] = computeCheckSum(packet); //COMPUTE CHECKSUM 
     send(packet); //SEND PACKET 
     Thread.sleep(4000); //WAIT TO SEND NEXT PACKET 
    }