Java sockety i problem z wysyłaniem pliku

0

Witam, piszę aplikację klient-server która będzie wysyłać pliki do servera. Mój problem polega na tym, że nie mogę wysyłać plików które ważą więcej niż 1460 bajtów. Kiedy wysyłam taki plik server odbiera tylko 1460 pierwszych bajtów. oto mój kod

klient wysyła:

    public void sendToServer(File file) throws Exception
    {
        Log.i("======", "sendToServer==============");
        OutputStream output = sk.getOutputStream();     

        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] buffer = new byte[sk.getSendBufferSize()];
        int bytesRead = 0;

        while((bytesRead = fileInputStream.read(buffer))>0)
        {
            output.write(buffer,0,bytesRead);
        }

        fileInputStream.close();
    }

server odbiera:

    public File odbierzPlik(String name) throws Exception
    {
        System.out.println("odbieram");
        File file=null;

        InputStream input = sk.getInputStream();

        file = new File("C://protokolPliki/" + name);
        FileOutputStream out = new FileOutputStream(file);

        byte[] buffer = new byte[sk.getSendBufferSize()];

        int bytesReceived = 0;

        while((bytesReceived = input.read(buffer))>0) {
            out.write(buffer,0,bytesReceived);
            break;
        }

        return file;
    }

Czy ktoś wie co robię źle? Googlowałem o tym trochę i myślę że może to mieć związek z MMS TCP które wynosi właśnie 1460 bajtów. Dzięki za wszelką pomoc.

0

Nie wiem czy o to chodzi, ale zle jest petla zapisujaca while read > 0: mozliwe ze nie zostanie wczytany zaden byte, ale to nie znaczy ze wiecej nie ma, tutaj powinno sie sprawdzac czy nastapil EOF czyli porownywac do -1.

0

jestem na 100% pewien, że plik dochodzi w całości, jednak możliwe że podzielony jest na części. Wymyśl sobie jakiś protokół wysyłania, a nie liczysz na to że serwer odbierze Ci to w takiej samej formie jak wyśle klient.

Tj. jak wysyłasz porcje danych:

<1024 bajty> [mija jakiś czas] <1234 bajty> to może to dojść zarówno tak: <1746 bajty> [jakiś czas] <512 bajtów> jak i: <1234b.> [jakiś czas] <1024b.> gwarantowane jest jedynie, że pakiet dojdzie. Odebrane dane powinieneś dzielić ręcznie tzn. np: zamiast wysłać X bajtów wysyłasz: <4 bajtowa liczba = X><x bajtów="bajtów" danych="danych"> wtedy przy odbieraniu będziesz wiedział jak te dane zinterpretować.
0

Musisz sobie odczytany plik wczytać do tablicy bajtowej a potem to pociąć najlepiej na równe paczki. Wyjdzie Ci ile paczek (określonej długośći) bedziesz wysyłał. Musisz sobie zdefiniować komunikaty które pójdą do serwera oznaczające, że transfer danych się rozpoczął i skończył (komunikaty mogą lecieć na tym samym porcie). W komunikacie rozpoczynajacych transfer zawierasz też informację ile paczek i jakiej długości oraz może być całkowita liczba bajtów pliku. NP.

String komunikatStart = "TRANSFER_START#2#4096#8012";
String komunikatStop = "TRANSFER_COMPLATE";

W pętli na serwerze bedziesz sobie parsował przychodzące dane pod względem własnie tych komunikatów. Dzięki temu będziesz wiedział na serwerze jaką tablicę zrobić i ile się danych spodziewać.

A teraz wysyłanie możesz np. zrealizować tak:

public void wyslijDane(byte[] data, int sizeOfPackage, boolean synchroTransfer, String synchroTransferMsg) throws IOException {

        int iloscPaczek = GeneralFileHandling.getNumberOfPackages(data.length, sizeOfPackage);
        AMMSLog.logger.fine("Dane podzielone na " + iloscPaczek + " paczek");
        for (int i = 0; i < iloscPaczek; i++) {

            int iloscDanychDoPrzeslania = sizeOfPackage;
            if (i == iloscPaczek - 1) {
                iloscDanychDoPrzeslania = data.length - (iloscPaczek - 1) * sizeOfPackage;
            }
            dataOutputStream.write(data, i * sizeOfPackage, iloscDanychDoPrzeslania);
            dataOutputStream.flush();
            if (synchroTransfer) {
                if (czytajKomunikat(false).equals(synchroTransferMsg)) {
                    //Potwierdzenie odbioru paczki
                }
            }
        }
    }

}

Tam jak widzisz też jest miejsce na synchroniczne wysyłanie danych tzn. po każdej paczce sewer potwierdza odbiór jakimś komunikatem. Np "MAM_PACZKE_N".

Ja sobie podział paczek załatwiłem taką metodą:

public static int getNumberOfPackages(int dataLenght, int sizeOfBuffer) {
        int iloscPaczek = (int) dataLenght / sizeOfBuffer;
        if (iloscPaczek == 0) {
            iloscPaczek++;
        } else {
            if (iloscPaczek == 1) {
                if (dataLenght > sizeOfBuffer) {
                    iloscPaczek++;
                }
            } else {
                if (dataLenght % iloscPaczek != 0) {
                    iloscPaczek++;
                }
            }
        }
        return iloscPaczek;
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0