2014-04-03 2 views
0

Java에서 TFTP 클라이언트를 구현하려고합니다. 클라이언트는 Localhost에서 완벽하게 작동하며 네트워크를 통해 TFTP 서버로 전송하는 경우가 있습니다. 그러나 때로는 내 DatagramSocket가 패킷 수신을 임의로 중단합니다. 읽기/쓰기 요청을 보내지 만 서버가 다시 보내려는 다음 메시지를 수신하지 않습니다. Wireshark를 확인했는데 서버가 확실히 수신하고 전송하려고합니다. 방화벽은 필요한 곳에서 꺼집니다. 문제가 무엇인지 알 수 없습니다.DatagramSocket은 무작위로 패킷 수신을 중지합니다 (가끔 받기도 함)

public class TFTPClient { 
String filename; 
String mode; 
boolean read; 
PacketBuilder builder; 
String IP; 
JFrame frame; 
public TFTPClient(String uifilename, String uimode, boolean uiread, String uiIP, JFrame uiFrame){ 
    this.filename = uifilename; 
    this.read = uiread;  
    this.mode = uimode; 
    this.IP = uiIP; 
    builder = new PacketBuilder(); 
    this.frame = uiFrame; 
} 


/* 
* Method choses between reading a file and writing a file based on boolean selected in main UI. 
*/ 
public void startTFTP() throws IOException{ 
    if (read){ 
     readFile(); 
    } 
    else{ 
     writeFile(); 
    } 
} 
/* 
* Method is used for writing a file 
*/ 
private void writeFile() throws IOException{ 
    byte[] WRQ = builder.getWRQ(filename,mode); 
    String filenameAndExtension = filename; 
    RandomAccessFile f = new RandomAccessFile(filenameAndExtension, "r"); 
    byte[] fileBytes = new byte[(int)f.length()]; 
    f.read(fileBytes); 
    f.close(); 



    DatagramSocket TFTPSocket = new DatagramSocket(); 
    TFTPSocket.setSoTimeout(5000); 


    //create the packet and send to port 69 of the given IP 
    DatagramPacket wrqPacket = new DatagramPacket(WRQ, WRQ.length, 
      InetAddress.getByName(IP), 69); 

     try { 
      TFTPSocket.send(wrqPacket); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
     byte[] ackByte = new byte[4]; 
     DatagramPacket ackPacket = new DatagramPacket(ackByte, 
       ackByte.length); 
     int blockNumber = 0; 
     DatagramPacket dataPacket; 
     boolean terminateOnNextAck = false; 
     boolean needExtraDataPacket = false; 
     int currentIndex = 0; 
     while(true) 
     { 
      TFTPSocket.receive(ackPacket); 
      System.out.println("Server acked " + ackByte[3]); 
      System.out.println("Expected ack " + blockNumber); 

      blockNumber++; 

      if(terminateOnNextAck){ 
       break; 
      } 


      byte[]DATAdata; 
      if (needExtraDataPacket){ 
       DATAdata = new byte[0]; 
       terminateOnNextAck = true; 
      } 
      else if (currentIndex + 512 > fileBytes.length){ 
       //This is our last byte. Length will be smaller than 508 
       DATAdata = new byte [fileBytes.length - currentIndex]; 
       terminateOnNextAck = true; 
      } 
      else{ 
       DATAdata = new byte[512]; 
      } 
      if (currentIndex + 512 ==fileBytes.length){ 
       needExtraDataPacket = true; 
      } 
      for (int i = 0; i<DATAdata.length; i++){ 
       DATAdata[i] = fileBytes[currentIndex]; 
       currentIndex++; 

      } 

      byte[] DATA = builder.getData(DATAdata, blockNumber); 


      dataPacket = new DatagramPacket(DATA, DATA.length, 
        InetAddress.getByName(IP),ackPacket.getPort());   
       try { 
        TFTPSocket.send(dataPacket); 
       } catch (IOException e) { 
        e.printStackTrace(); 
        System.exit(1); 
       } 
     } 
     TFTPSocket.close(); 
     System.out.println("Write sucessful"); 

} 
/* 
* Method is used for reading a file 
*/ 
private void readFile() throws IOException{ 
    //Get RRQ packet 
    byte[] RRQ = builder.getRRQ(filename,mode); 
    StringBuffer fileText = new StringBuffer(); 

    DatagramSocket TFTPSocket = new DatagramSocket(); 
    TFTPSocket.setSoTimeout(5000); 
    //create the packet and send to port 69 of the given IP 
    DatagramPacket rrqPacket = new DatagramPacket(RRQ, RRQ.length, 
      InetAddress.getByName(IP), 69); 

     try { 
      TFTPSocket.send(rrqPacket); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
     byte[] dataByte = new byte[516]; 
     for (int i = 516;i<516;i++){ 
      dataByte[i] = 0; 
     } 
     DatagramPacket dataPacket = new DatagramPacket(dataByte, 
       dataByte.length); 
     System.out.println("Client: Waiting for packet."); 
     DatagramPacket ackPacket; 
     boolean error = false; 
     while(true) 
     { 
      TFTPSocket.receive(dataPacket); 
      System.out.println(TFTPSocket.getLocalPort()); 
      if (dataByte[1] == 5){ 
       error = true; 
       break; 
      } 
      fileText.append(new String(dataPacket.getData(),0,dataPacket.getLength())); 
      byte blockNumbers[] = new byte[2]; 
      blockNumbers[0] = dataByte[2]; 
      blockNumbers[1] = dataByte[3]; 
      byte[] ACK = builder.getACK(blockNumbers); 
      ackPacket = new DatagramPacket(ACK, ACK.length, 
        InetAddress.getByName(IP),dataPacket.getPort()); 

       try { 
        TFTPSocket.send(ackPacket); 
       } catch (IOException e) { 
        e.printStackTrace(); 
        System.exit(1); 
       } 

      if (dataByte[515] == 0){ 
       break; 
      } 
      dataByte[515] = 0; 
     } 

     if (!error){ 
      JOptionPane.showMessageDialog(frame, "Read Successful!"); 
     System.out.println(fileText); 
     } 
     else{ 
      JOptionPane.showMessageDialog(frame,"Error from server: " + new String(dataPacket.getData(),0,dataPacket.getLength())); 
     }  
} 
} 
+0

이 비슷한 문제가 발생했습니다.이 stackoverflow http://stackoverflow.com/questions/8314174/datagramsocket-temporarily-stops-receiving-packets-java. Java UDP 스택에 문제가 있습니까? –

+0

다음 stackoverflow 게시물을 살펴보십시오. http://stackoverflow.com/questions/20213953/receiving-udp-in-java-without-dropping-packets http://stackoverflow.com/questions/7968566/what- 원인 - udp-packets-to-be-drop-being-being-local-to-localhost –

+0

@RichardChambers 'Java UDP 스택'이 없습니다. Java는 C 소켓 API를 통해 단순한 계층을 제공합니다. UDP 스택은 커널에 있습니다. – EJP

답변

0

이 문제는 프로그램은 Windows에서 잘 실행 맥 OS X에서 뭔가 밝혀졌다 : 여기에 내가 사용하고있는 코드입니다. 왜 그런지 완전히 모르겠습니다.

관련 문제