0

我正在创建一个 DatagramPacket,我试图通过一个面向更好且更可靠的 UDP 协议(​​手动创建:我手动添加一个带有校验和、序列号和长度的标头)发送到我的“本地主机”数据),然后等待来自服务器的确认。

一开始一切都还好,我发送了很多文件,一些只有 1 个数据包长度(1000 字节),其他的每个 1000 字节有 20 个数据包,我没有问题,服务器以正确的 ACK(确认)响应,并且一切都好!但不知何故,5分钟后,我的程序不再发送文件,它只发送一个数据包,然后因异常停止......

java.net.SocketTimeoutException: Receive timed out
at java.net.DualStackPlainDatagramSocketImpl.socketReceiveOrPeekData(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.receive0(Unknown Source)
at java.net.AbstractPlainDatagramSocketImpl.receive(Unknown Source)
at java.net.DatagramSocket.receive(Unknown Source)
at blatt7.FileSender.sendFile(FileSender.java:100)
at blatt7.FileSender.main(FileSender.java:184)"

对不起,代码太长了,但如果有人可以提供帮助,那就太好了!谢谢!这是我的客户代码:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.file.*;
import java.util.zip.CRC32;

public class FileSender {

DatagramSocket sock = null;
CRC32 checksumRechner = new CRC32();
private byte[] readLength;
private byte[] seqNrArray;
private byte[] checksumArray;
private String dateiPfad;
private String zielRechner;
private InetAddress host;
private File datei;
private int seqNr = 1;
FileInputStream fis;
int counter = 0;
byte[] daten = new byte[1000];
byte[] header = new byte[16];
byte[] packet;
byte[] ack_buffer = new byte[4];
int port = 7777;
DatagramPacket dp;
DatagramPacket ack_dp = new DatagramPacket(ack_buffer, ack_buffer.length);
private long receivedSeqNr = 0;
private int readLen;

public FileSender(String zielRechner, String dateiPfad) throws IOException {
    this.setZielRechner(zielRechner);
    this.setDateiPfad(dateiPfad);
    setHost(InetAddress.getByName(zielRechner));
    setDatei(new File(dateiPfad));
    fis = new FileInputStream(datei);
}

public void sendFile() throws IOException {
    while((readLen = fis.read(daten)) != -1) {
        if (getSeqNr() == 1)
            seqNr = 0;
        else
            seqNr = 1;

        readLength = intToBytes(readLen);

        for (int i = 0; i < readLength.length; i++) {
            header[8+i] = readLength[i];
        }

        seqNrArray = intToBytes(getSeqNr());

        for (int i = 0; i <seqNrArray.length; i++) {
            header[12+i] = seqNrArray[i];
        }

        packet = new byte[header.length + daten.length];

        //wir fügen Daten und Header ins Packet zusammen.
        int j=0; 
        for (int i=0; i<packet.length; i++) {
            if (i < header.length) 
                packet[i] = header[i];
            else { 
                packet[i] = daten[j];
                j++;
            }
        }

        //wir rechnen die prüfsumme
        checksumRechner.reset();
        checksumRechner.update(packet,8,8+readLen);

        checksumArray = longToBytes(checksumRechner.getValue());

        //wir schreiben uns checksum in das packet
        for(int i=0; i < 8; i++) {
            packet[i] = checksumArray[i];
        }

        dp = new DatagramPacket(packet , packet.length , host , port);

        while (receivedSeqNr == seqNr) {
            try {
                sock = new DatagramSocket();
                sock.send(dp);
                sock.setSoTimeout(7000);
                counter++;
                System.out.println("Paket sent with seqNr: " + getSeqNr() + " und Length: " + getReadLen() + " - PAKET NR: " + counter);
                sock.receive(ack_dp);
                ack_buffer = ack_dp.getData();
                receivedSeqNr = bytesToLong(ack_buffer,0);
                System.out.println("got SeqNr, with receivedSeq-Nr: " + receivedSeqNr);
            } catch (SocketTimeoutException e)
            { 
                e.printStackTrace();
                break;
            }
        }
    }
    fis.close();
}   


public static byte[] longToBytes(long value) {
    ByteBuffer buffer = ByteBuffer.allocate(8);
    buffer.putLong(value);
    return buffer.array();
}

public static long bytesToLong(byte[] bytes, int index) {
    ByteBuffer buffer = ByteBuffer.allocate(8);
    buffer.put(bytes);
    buffer.flip();//need flip 
    return buffer.getLong(index);
}

public static byte[] intToBytes(int value) {
    ByteBuffer buffer = ByteBuffer.allocate(4);
    buffer.putInt(value);
    return buffer.array();
}

public static int bytesToInt(byte[] bytes, int index) {
    ByteBuffer buffer = ByteBuffer.allocate(4);
    buffer.put(bytes);
    buffer.flip();//need flip 
    return buffer.getInt(index);
}

public String getDateiPfad() {
    return dateiPfad;
}

public void setDateiPfad(String dateiPfad2) {
    this.dateiPfad = dateiPfad2;
}

public String getZielRechner() {
    return zielRechner;
}

public void setZielRechner(String zielRechner) {
    this.zielRechner = zielRechner;
}

public InetAddress getHost() {
    return host;
}

public void setHost(InetAddress host) {
    this.host = host;
}

public File getDatei() {
    return datei;
}

public void setDatei(File datei) {
    this.datei = datei;
}

public int getSeqNr() {
    return seqNr;
}

public int getReadLen() {
    return readLen;
}

public static void main(String[] args) throws IOException,ClassNotFoundException {

    FileSender sender = new FileSender("localhost", "C:/Users/Kb/Desktop/wifi pops.txt");
    sender.sendFile();

}

}

和我的服务器代码:

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.zip.CRC32;

公共类 FileReceiver {

static byte[] buffer;
DatagramPacket incoming;
DatagramSocket serverSock = null;
CRC32 checksumRechner = new CRC32();
int dataLength;
long checksumReceiver;
long checksumSender;
int port = 7777;
int receivedSeqNr;

public FileReceiver() {
    buffer = new byte[1500];
    incoming = new DatagramPacket(buffer, buffer.length);
}

public void receive() {
    try
    {
        //1. Erstellung eines server sockets, parameter ist localportnummer
        serverSock = new DatagramSocket(port);
        serverSock.setSoTimeout(10000);

        //2. Warten für incoming data
        echo("Server socket created. Waiting for incoming data...");

        //kommunikationsloop
        while(true)
        {   
            serverSock.receive(incoming);

            byte[] dataLengthArray = new byte[4];
            for (int i=0; i <4; i++) {
                dataLengthArray[i] = buffer[i+8];
            }
            dataLength = FileSender.bytesToInt(dataLengthArray,0);

            checksumRechner.reset();
            checksumRechner.update(buffer, 8, dataLength+8);


            checksumReceiver = checksumRechner.getValue();

            byte[] receivedSeqNrArray = new byte[4];
            for (int i=0; i <4; i++) {
                receivedSeqNrArray[i] = buffer[i+12];
            }
            receivedSeqNr = FileSender.bytesToInt(receivedSeqNrArray,0);

            byte[] receivedChecksumArray = new byte[8];
            for (int i=0; i <8; i++) {
                receivedChecksumArray[i] = buffer[i];
            }
            long receivedChecksumNr = FileSender.bytesToLong(receivedChecksumArray,0);

            System.out.println("Paket received with checksum: " + receivedChecksumNr);
            System.out.println("Server-generated checksum: " + checksumReceiver);
            System.out.println("Paket got, with seqNr: " + receivedSeqNr + " und length: " + dataLength);
            if (checksumReceiver != receivedChecksumNr)  {
                sendACK(receivedSeqNr);
                System.out.println("Paket has errors! Must be sent again!");
            }
            else if(checksumReceiver == receivedChecksumNr && receivedSeqNr == 1) {
                sendACK(0);
                System.out.println("SeqNr sent --> SeqNr: 0");
            }
            else if (checksumReceiver == receivedChecksumNr && receivedSeqNr == 0) {
                sendACK(1);
                System.out.println("SeqNr sent --> SeqNr: 1");
            }


         }
     }
     catch(IOException e)
     {
         System.err.println("IOException " + e);
     }
 }


 //echo data ausgeben
public static void echo(String msg)
{
    System.out.println(msg);
}

public void sendACK(int seqNum) throws IOException {
    byte[] sendArray = FileSender.intToBytes(seqNum);
    DatagramPacket sendPacket = new DatagramPacket(sendArray, sendArray.length, InetAddress.getByName("localhost"), 7777);
    serverSock.send(sendPacket);
}

public static void main(String[] args) throws IOException,ClassNotFoundException {

    FileReceiver receiver = new FileReceiver();
    receiver.receive();

}

}
4

0 回答 0