当前位置: 首页 > 知识库问答 >
问题:

DatagramSocket将随机停止接收数据包(有时仍会接收)

段干弘毅
2023-03-14

我正在尝试用Java实现一个TFTP客户端。客户端在Localhost上运行良好,有时可以通过网络发送到TFTP服务器。然而,有时我的DatagramSocket会随机停止接收数据包。它将发送读/写请求,但永远不会收到服务器试图发送回的下一条消息。我已经检查了Wireshark,服务器确实在接收和尝试发送。防火墙在需要的地方被关闭。无法找出问题所在。以下是我正在使用的代码:

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()));
       }    
}   
}

共有1个答案

何海
2023-03-14

这个问题原来是苹果操作系统的问题。该程序在视窗系统上运行良好。不过,不完全确定为什么。

 类似资料:
  • 问题内容: 谁能给我展示一个Java实例来从DatagramSocket接收数据并通过Multicast Socket发送相同的数据 问题答案: 发送多播数据报 为了用Java发送任何类型的数据报,无论是单播,广播还是多播,都需要一个: 可以选择将本地端口提供给套接字必须绑定到的DatagramSocket构造函数。仅当一个人需要其他方能够在特定港口与我们联系时才需要这样做。第三个构造函数获取要绑

  • 我有一个很奇怪的问题快把我逼疯了。 我有一个Ruby服务器和一个Flash客户端(动作脚本3)。这是一个多人游戏。 问题是,一切都在完美地工作,然后,突然,一个随机的球员停止接收数据。当服务器因为不活动而关闭连接时,大约20-60秒后,客户端接收到所有缓冲的数据。 null 我不认为这是一个操作系统/网络问题,因为我已经从一个位于西班牙的VPS换到了位于爱尔兰的亚马逊EC2,问题仍然存在。 我觉得

  • 我想这个话题发生了什么...偏移坏了还是我不知道... 有人知道会发生什么吗?谢谢

  • 目前,我正在开发一个用于处理原始机器测量数据的storm拓扑。然而,我遇到了无法解释的问题与喷口。 我正在Azure HDInsight上运行一个简单的storm拓扑,用Java编写。事件是从eventhub中读取的,我使用microsoft eventhub spout(版本0.9)。这个eventhub有8个分区,这意味着我也需要EventhUbspout的8个实例。 但是,当我运行拓扑几个小

  • 我不知道是网络配置还是我的软件出了问题。 这是监听代码: 奇怪的是,在wireshark上,我可以看到:数据包已从发送到,并且设备已对此数据包作出响应--来自的数据包已发送到。使用bind(0.0.0.0,端口)似乎不能涵盖。我迷路了,一点主意都没有。 ifconfig为: