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()));
}
}
}
이 비슷한 문제가 발생했습니다.이 stackoverflow http://stackoverflow.com/questions/8314174/datagramsocket-temporarily-stops-receiving-packets-java. Java UDP 스택에 문제가 있습니까? –
다음 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 –
@RichardChambers 'Java UDP 스택'이 없습니다. Java는 C 소켓 API를 통해 단순한 계층을 제공합니다. UDP 스택은 커널에 있습니다. – EJP