Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java DatagramSocket将随机停止接收数据包(有时仍会接收)_Java_Sockets_Udp_Datagram_Tftp - Fatal编程技术网

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

Java DatagramSocket将随机停止接收数据包(有时仍会接收),java,sockets,udp,datagram,tftp,Java,Sockets,Udp,Datagram,Tftp,我正在尝试用Java实现一个TFTP客户机。客户端可以在本地主机上完美地工作,有时还可以通过网络发送到TFTP服务器。然而,有时我的DatagramSocket会随机停止接收数据包。它将发送读/写请求,但从未收到服务器试图发回的下一条消息。我已经检查了Wireshark,服务器肯定正在接收并尝试发送。在需要的地方关闭防火墙。我想不出是什么问题。以下是我正在使用的代码: public class TFTPClient { String filename; String mode; boolean

我正在尝试用Java实现一个TFTP客户机。客户端可以在本地主机上完美地工作,有时还可以通过网络发送到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()));
       }    
}   
}
公共类TFTPClient{
字符串文件名;
字符串模式;
布尔读取;
包装制造商;
字符串IP;
JFrame框架;
公共TFTPClient(字符串uifilename、字符串uimode、布尔uiread、字符串uiIP、JFrame uiFrame){
this.filename=uifilename;
this.read=uiread;
this.mode=uimode;
this.IP=uiIP;
builder=新的PacketBuilder();
this.frame=uiFrame;
}
/*
*方法根据主UI中选择的布尔值在读取文件和写入文件之间进行选择。
*/
public void startTFTP()引发IOException{
如果(读){
readFile();
}
否则{
writeFile();
}
}
/*
*方法用于写入文件
*/
私有void writeFile()引发IOException{
字节[]WRQ=builder.getWRQ(文件名,模式);
字符串filename和extension=filename;
RandomAccessFile f=新的RandomAccessFile(文件名和扩展,“r”);
byte[]fileBytes=新字节[(int)f.length()];
f、 读取(文件字节);
f、 close();
DatagramSocket TFTPSocket=新的DatagramSocket();
TFTPSocket.setosotimeout(5000);
//创建数据包并发送到给定IP的端口69
DatagramPacket wrqPacket=新的DatagramPacket(WRQ,WRQ.length,
InetAddress.getByName(IP),69);
试一试{
TFTPSocket.send(wrqPacket);
}捕获(IOE异常){
e、 printStackTrace();
系统出口(1);
}
字节[]ackByte=新字节[4];
DatagramPacket ackPacket=新的DatagramPacket(ackByte,
ackByte.length);
int blockNumber=0;
数据包;
布尔terminateOnNextAck=false;
布尔值needExtraDataPacket=false;
int currentIndex=0;
while(true)
{
TFTPSocket.receive(ackPacket);
System.out.println(“服务器已确认”+ackByte[3]);
System.out.println(“预期确认”+区块编号);
blockNumber++;
如果(terminateOnNextAck){
打破
}
字节[]数据数据;
如果(需要外部数据包){
DATAdata=新字节[0];
terminateOnNextAck=true;
}
else if(currentIndex+512>fileBytes.length){
//这是最后一个字节。长度将小于508
DATAdata=新字节[fileBytes.length-currentIndex];
terminateOnNextAck=true;
}
否则{
DATAdata=新字节[512];
}
if(currentIndex+512==fileBytes.length){
needExtraDataPacket=true;
}

对于(int i=0;i这个问题原来是Mac OS X的问题。该程序在Windows上运行良好。但不完全确定原因。

这个stackoverflow看到了类似的问题。Java UDP堆栈有问题吗?还可以看看下面的stackoverflow帖子:@RichardChambers没有“Java UDP堆栈”。Java只是提供了一个C sockets API上的n层。UDP堆栈在内核中。你找到过这个问题的答案吗?目前我在macOS/Java上观察到一个UDP问题,没有找到太多关于它的内容。。。