Android: изображение, полученное через сокет, повреждено

#android #sockets #file-transfer

#Android #сокеты #передача файлов

Вопрос:

Привет, вот проблема: сервер отправляет изображение клиенту правильно (я думаю). Файл, полученный от клиента, имеет тот же размер, что и файл, присутствующий на сервере phone, поэтому, я думаю, каждый байт был передан, но изображение все равно не видно. Либо сервер, либо клиент являются телефонами Android. Заранее спасибо, надеюсь, вы сможете мне помочь.

Код сервера:

 public class FileActivity extends Activity {

private FileInputStream fileInputStream;
private BufferedInputStream bufferedInputStream;
private OutputStream outputStream;

private byte [] mybytearray;

private String tmp = null;

private TextView tv;

private File myFile;

private int l;

private String path;

private EditText editText;

private ServerSocket serverSocket;

private Socket client;

public static String SERVERIP = "10.0.2.15";

private final int SERVERPORT = 8080;

private byte [] imgbyte;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_file);

    tv = (TextView) findViewById(R.id.textView1);
    editText = (EditText) findViewById(R.id.editText1);

    SERVERIP = getLocalIpAddress();

    Thread sThread = new Thread(new ServerThread());
    sThread.start();
}

public void sendListener(View v) {

    tmp = editText.getText().toString();

    path = "/sdcard/"   tmp;

    myFile = new File(path);Log.d("SERVER", "WORKS");           

    l = (int) myFile.length();Log.d("SERVER", "WORKS");

    tv.setText(path   "  "   Integer.toString(l));  

    tmp = Integer.toString(l);  Log.d("SERVER", "WORKS");

    String test = tmp;



    //out.println(tmp);
    Log.d("SERVER", "WORKS");
    try {

        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
        out.println(test);
        //out.close();
        Log.d("SERVER", "WORKS");
        byte[] mybytearray = new byte[1024]; //create a byte array to file
        Log.d("SERVER", "WORKS");
        fileInputStream = new FileInputStream(myFile);
         bufferedInputStream = new BufferedInputStream(fileInputStream);  
         Log.d("SERVER", "WORKS");


         Log.d("SERVER", "WORKS");
         try{
             outputStream = client.getOutputStream();
         } catch(Exception e)
         {
             Log.d("OUTPUT", "UFFFF");
             e.printStackTrace();
         }
        /* Log.d("SERVER", "ALMOST");
         outputStream.write(mybytearray, 0, mybytearray.length); Log.d("SERVER", "DONE");//write file to the output stream byte by byte*/
      //  outputStream.flush();
       // outputStream.close();

         Log.d("SERVER", "WORKS");
         int count = 0;
         int size = 0;

         while((count = bufferedInputStream.read(mybytearray, 0 , mybytearray.length)) != -1)
         {
            // count = bufferedInputStream.read(mybytearray, 0 , mybytearray.length);
             size  = count;
             Log.d("SERVER", "SEND");
             try{
                 outputStream.write(mybytearray, 0, count);
             } catch(Exception e) {
                 e.printStackTrace();
             }

             Log.d("TEST", Integer.toString(count));
         }
         Log.d("SERVER", "DONE");
         bufferedInputStream.close();
         outputStream.close();
               client.close();
    } catch (Exception e) {

    }   


}


public class ServerThread implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            serverSocket = new ServerSocket(SERVERPORT);
            client = serverSocket.accept();
            //outputStream = client.getOutputStream();

            Log.d("SERVER", "Connesso");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Log.d("TEST", "UFFFAAA");
        }           
    }

}

private String getLocalIpAddress() {

    String tmp = "";

    int i = 0;

    try {
        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
            NetworkInterface intf = en.nextElement();
            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                if (!inetAddress.isLoopbackAddress()) 
                { 

                    tmp  = "IP: "   inetAddress.getHostAddress()   "n"; 

                }
            }
        }
    } catch (SocketException ex) {
        Log.e("ServerActivity", ex.toString());
    }
    return tmp;
}

@Override
protected void onStop() {
    super.onStop();
    try {
         serverSocket.close();
     } catch (IOException e) {
         e.printStackTrace();
     }
}
  

}

Клиентский код:

 public class FileActivity extends Activity {

private EditText serverIp, getPort;
private Button connectPhones;
private TextView tv, tvIP;

private Boolean connected = false;

private String serverIpAddress, portStr;

private Socket socket;

private int port, len;

private String filepath;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_file);

    tvIP = (TextView) findViewById(R.id.IPtv);
    tv = (TextView) findViewById(R.id.Portatv);
    serverIp = (EditText) findViewById(R.id.server_ip);
    connectPhones = (Button) findViewById(R.id.connect_phones);
    getPort = (EditText) findViewById(R.id.server_port); 
}

public void connectListener(View v)
{
    if (!connected) {
        serverIpAddress = serverIp.getText().toString();
        portStr = getPort.getText().toString();
        if (!serverIpAddress.equals("")) {
            Thread cThread = new Thread(new ClientThread());
            cThread.start();
        }
    }
}

public class ClientThread implements Runnable
{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        port = Integer.parseInt(portStr);

        socket = new Socket();

        try {
            InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
            Log.d("ClientActivity", "C: Connessione in corso...");
            socket = new Socket(serverAddr, port);
            Log.d("ClientActivity", "C: Connesso!");
            connected = true;

            DataInputStream dis;
            try {
                dis = new DataInputStream(socket.getInputStream());
                int bytes;
                byte[] b = new byte[32];
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String l = in.readLine();
                //String line = Integer.toString(l);
                Log.d("PROVA", l);  
                try
                {
                    len = Integer.parseInt(l); Log.d("CLIENT", Integer.toString(len));
                }
                catch (NumberFormatException e)
                {
                    e.printStackTrace();
                }
                byte[] img = new byte[1082922];  //1082922
                FileOutputStream fos = new FileOutputStream("/sdcard/img.jpg");
                BufferedOutputStream bos = new BufferedOutputStream(fos);

                /*bytes = dis.read(img, 0, img.length);

                bos.write(img, 0, img.length);*/
                int count = 0;
                while ((bytes = dis.read(img)) != -1) {
                    count  = bytes;
                    Log.d("CLIENT", Integer.toString(count));
                    Log.d("TEST", Integer.toString(bytes));
                    //Write to file
                    bos.write(img, 0, bytes);
                }
                bos.flush();
                bos.close();
                Log.d("TCP", "Save to file");
            } catch(IOException e){
                e.printStackTrace();
            }                

        } catch (Exception e) {
            Log.e("ClientActivity", "C: Errore", e);
            connected = false;
        }
    }

}

 @Override
    protected void onStop() {
        super.onStop();
        if(connected == true)
        {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }    
  

}

Комментарии:

1. В sendListener на стороне сервера — вы читаете первые 1024 байта из BufferedInputStream — никогда не сохраняя их нигде — прежде чем начать фактический цикл чтения / записи.

2. На самом деле вы правы, я этого не заметил! Спасибо! Теперь сервер отправляет все байты! К сожалению, на стороне клиента изображение повреждено, его вообще не видно.. Можете ли вы помочь мне дальше? Заранее большое вам спасибо

Ответ №1:

Вы объединяете буферизованный и небуферизованный ввод-вывод в одних и тех же базовых потоках. Буферизованный считыватель украдет данные из другого потока, заполнив его буфер тем, что доступно. У вас есть потоки ввода и вывода данных: используйте их для всего. Вы можете отправить размер файла с помощью writeInt() / readInt().

Комментарии:

1. Так вот почему полученное изображение повреждено?

2. Конечно, это так. Неверные данные — = повреждение, не так ли?

Ответ №2:

У вас уже есть одно .read() перед while циклом. И эти байты вы не делаете write() , поэтому клиент не получает первые байты файла. O теперь я вижу, что вы их записываете, но не учитываете их размер. В любом случае: плохая конструкция. И для первого чтения вы также должны были использовать переменную count. И записывайте только количество байтов. Лучше полностью удалить первое чтение.

Комментарии:

1. Итак, ошибок нет? И есть идеи, почему сервер не отправляет все байты?

2. Ваш вопрос не имеет смысла. Пожалуйста, внимательно перечитайте то, что я написал.

3. Я не понимаю, что вы имеете в виду. Первый «read ()» предназначен для определения размера файла, а второй «read ()» — для получения самого файла.

4. О, извините, это идея. Хорошая идея сначала отправить размер файла. Но, пожалуйста, объясните, как передается размер. И на стороне сервера вы сначала резервируете 32 байта, после чего вы читаете строку. И вы не извлекаете из него значение. Вместо этого вы используете фиксированный буфер. Я не могу следовать вашему коду. Пожалуйста, объясните.

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