2017-04-04 15 views
0

자바의 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... 

그런 다음 그 이후 각

는 SO가 다시 검사를 얻기 위해 그 후 나사, 제대로 한 번 검사를 받고있다 .... 유효하지 않습니다. 나는 자바에서 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를 사용하고 1 바이트 만 전송합니까? 이것은 말이되지 않습니다. – EJP

답변

1

체크섬을 계산할 때는 packet[2]을 0으로 설정해야합니다. 코드의 일부분, 즉 함수 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 
    }