DatagramSocket: отправка файла, клиент не получает файл изображения - PullRequest
1 голос
/ 15 декабря 2011

Я пытаюсь отправить кучу файлов с помощью DatagramSocket.Но есть проблема, которую я не могу понять.Передача файлов, отличных от файлов изображений, проходит хорошо, но при отправке файлов изображений Клиент застревает при получении, хотя Сервер отправляет файл.Вот мои клиентские и серверные блоки кода:

Сервер:

    while (true) {
        System.out.print("DatagramSocket: Waiting for file request...\n");
        buf = new byte[Integer.SIZE];
        packet = new DatagramPacket(buf, buf.length);
        datagramSocket.receive(packet);
        bb = ByteBuffer.wrap(buf);

        // Receive request
        buf = new byte[bb.getInt()];
        packet = new DatagramPacket(buf, buf.length);
        datagramSocket.receive(packet);

        System.out.print("DatagramSocket: File request received.\n");
        System.out.print("DatagramSocket: Requested file: "+new String(buf)+"\n");

        // Check file if it is exist.
        File file = new File("kaynak/"+new String(buf));

        if (!file.exists()) {
            System.out.print("DatagramSocket: File not found!\n");
            return;
        }

        // Send file length.
        System.out.printf("DatagramSocket: Sending file length: %d\n", file.length());
        bb = ByteBuffer.allocate(Integer.SIZE).putInt((int) file.length());
        buf = bb.array();
        packet.setData(buf);
        packet.setLength(buf.length);
        datagramSocket.send(packet);

        // Send file's relative path.
        String relativePath = file.getAbsolutePath().substring(System.getProperty("user.dir").length() + 1);
        System.out.printf("DatagramSocket: Sending file relative path: %s\n", relativePath);
        bb.putInt(relativePath.getBytes().length);
        datagramSocket.send(packet);
        packet.setData(relativePath.getBytes());
        packet.setLength(relativePath.getBytes().length);
        datagramSocket.send(packet);

        // Save file to byte array.
        bis = new BufferedInputStream(new FileInputStream(file));
        fileByteArray = new byte[(int) file.length()];
        bis.read(fileByteArray);

        System.out.printf("DatagramSocket: Sending file.\n");
        int r = (int) file.length();
        int c = 0;

        // Send file.
        for (int i = 0; i < file.length(); i++) {
            c = r < 512 ? r : 512;
            packet.setData(ByteBuffer.wrap(fileByteArray, i, c).array());
            packet.setLength(c);
            datagramSocket.send(packet);
            r -= 512;
            i += 511;
        }
        System.out.printf("DatagramSocket: File send.\n\n");
    }

Клиент:

// Send file request.
bb = ByteBuffer.allocate(Integer.SIZE).putInt(files.get(i).getBytes().length);
message = bb.array();
packet = new DatagramPacket(message, message.length, InetAddress.getByName(host), dport);
datagramSocket.send(packet);
message = files.get(i).getBytes();
System.out.print("Requesting: "+new String(message)+"\n");
packet.setData(message);
packet.setLength(message.length);
datagramSocket.send(packet);

// Receive file size.
System.out.print("Requesting file length.\n");
message = ByteBuffer.allocate(Integer.SIZE).array();
packet.setData(message);
packet.setLength(Integer.SIZE);
datagramSocket.receive(packet);
bb = ByteBuffer.wrap(message);
int arraySize = bb.getInt();
System.out.printf("File size = %d baytes.\n", arraySize);
fileByteArray = new byte[arraySize];

// Receive file's relative path.
System.out.print("Requesting file's relative path.\n");
datagramSocket.receive(packet);
message = ByteBuffer.allocate(message.length).array();
packet.setLength(message.length);
datagramSocket.receive(packet);
String htmlPath = new String(packet.getData());
System.out.printf("File's relative path = %s.\n", htmlPath);
File file = new File("hedef/"+htmlPath.substring("kaynak".length()));
file.getParentFile().mkdirs();
file.createNewFile();

// Receive file content.
System.out.print("Requesting file content.\n");
int r = arraySize;
int c = 0;

for (int j = 0; j < arraySize; j++) {
    c = r < 512 ? r : 512;
    packet.setData(ByteBuffer.wrap(fileByteArray, j, c).array());
    packet.setLength(c);
    datagramSocket.receive(packet);
    r -= 512;
    j += 511;
}

// Save file.
System.out.print("Saving file.\n");
bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(fileByteArray);
bos.flush();
System.out.print("File saved.\n\n");

Я также признателен, если можете дать мне подсказки о моем коде,производительность или неправильные советы по использованию.
Заранее спасибо.

Обновление:

После добавления небольшого времени ожидания цикла for, который отправляет сам файл, теперь яв состоянии завершить отправку файлов, но все полученные файлы изображений повреждены.

for (int j = 0; j < arraySize; j++) {
    c = r < 512 ? r : 512;
    packet.setData(ByteBuffer.wrap(fileByteArray, j, c).array());
    packet.setLength(c);
    datagramSocket.receive(packet);
    r -= 512;
    j += 511;
    Thread.sleep(50);
}

1 Ответ

2 голосов
/ 16 декабря 2011

Из документации DatagramSocket: этот метод блокируется до получения дейтаграммы.Очевидно, что пакеты теряются.

Также: было бы лучше не выделять массив для данных о дырах, которые будут получены.Вспомните какой-нибудь видеофайл размером 4 ГБ ... Вместо этого выделите буферный массив размером с чтение (512) и запишите его в BufferedOutputStream сразу после DatagramSocket.receive ().

...