2015-08-15 3 views
0

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

  1. Я получаю снимок экрана с компьютера с помощью робота.
  2. Я сохраняю его как Send.jpg.
  3. отправлю изображение. Скажем, например, его размер составляет 1 МБ.
  4. Получаю изображение по телефону.
  5. Я показываю его в ImageView.
  6. И повторите эти шаги, пока пользователь не закроет действие на телефоне.

Но результат таков:

Я получаю первый скриншот (Send.jpg: 1 MB) отправить его и получить его по телефону. Получите второй (Send.jpg: 2 MB) отправьте его и получите его по телефону. и третий и т. д.

Он никогда не отображается на телефоне. И когда я проверяю хранилище телефона с помощью проводника, я вижу одно изображение - его размер - это размер первого изображения + второй + третий ...

Я думаю, моя проблема в том, что я должен остановить InputStream, пожалуйста Помогите.

Код:

Сервер:

package application; 

import java.awt.AWTException; 
import java.awt.Rectangle; 
import java.awt.Robot; 
import java.awt.Toolkit; 
import java.awt.image.BufferedImage; 
import java.io.BufferedInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.io.PrintStream; 
import java.net.Socket; 

import javax.imageio.ImageIO; 

public class ScreenCapture { 

    Socket socket; 
    OutputStream os; 
    Robot robot; 
    PrintStream ps; 

    public ScreenCapture() throws IOException, AWTException { 
     // TODO Auto-generated constructor stub 
     socket = SocketWrapper.getSocket(); 
     os = socket.getOutputStream(); 
     robot = new Robot(); 
     ps = new PrintStream(socket.getOutputStream()); 
     new Record().start(); 

    } 

    private class Record extends Thread{ 
     @Override 
     public void run() { 
      while(true){ 
       int count; 
       Rectangle rect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); 
       BufferedImage img = robot.createScreenCapture(rect); 

       try { 
        ImageIO.write(img, "jpg", new File("/Users/Tomahawk/Documents/MovieMaker/send.jpg")); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       FileInputStream fis; 
       try { 
        File f = new File("/Users/Tomahawk/Documents/MovieMaker/send.jpg"); 
        fis = new FileInputStream(f); 
        BufferedInputStream bis = new BufferedInputStream(fis); 
        byte[] byteArray = new byte[(int) f.length()]; 
        long filesize = f.length(); 
        while((count = bis.read(byteArray)) > 0){ 
         os.write(byteArray,0,count); 
        } 
       } catch (IOException e1) { 
        // TODO Auto-generated catch block 
        e1.printStackTrace(); 
       } 
       System.out.println("Sent File"); 
      } 
     } 
    } 

} 

Client (Phone):

package com.pcontrol.tomahawk.pcontrol; 

import android.app.Activity; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.os.AsyncTask; 
import android.support.v7.app.ActionBarActivity; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.ImageView; 
import android.widget.Toast; 

import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.Socket; 
import java.util.Scanner; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 


public class ScreenCapture extends Activity { 

    Socket socket; 
    InputStream is; 
    OutputStream os; 
    Scanner scanner; 
    ImageView screenCap; 
    long filesize = 0; 
    int i=0; 

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

     socket = SocketWrapper.getSocket(); 
     try { 
      is = socket.getInputStream(); 
      scanner = new Scanner(is); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     screenCap = (ImageView) findViewById(R.id.screenCap); 

     new ReceiveFiles().execute(); 

    } 

    private class ReceiveFiles extends AsyncTask<Void,Void,Void> { 
     @Override 
     protected Void doInBackground(Void... params) { 

      try { 
       os = new FileOutputStream("/sdcard/"+i+".jpg"); 
       copy(is, os); 
       publishProgress(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      i++; 
      return null; 
     } 
     @Override 
     protected void onProgressUpdate(Void... values) { 
      Bitmap bmp = BitmapFactory.decodeFile("/sdcard/"+i+".jpg"); 
      screenCap.setImageBitmap(bmp); 
     } 
    } 

    static void copy(InputStream in, OutputStream out) throws IOException { 
     byte[] buf = new byte[60000]; 
     int len = 0; 
     while ((len = in.read(buf)) != -1) { 
      out.write(buf, 0, len); 
     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.menu_screen_capture, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 
} 

ответ

0

Вы не говорите приемник, где заканчивается один файл и следующий начинается.

Вы можете добавить базовый протокол кадрирования, например тот, где вы сначала отправляете размер файла, а затем данные. Таким образом, приемник может подсчитывать байты, которые он читает, и знает, когда закрыть текущий файл и открыть другой.

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

+0

Может также быть полезно установить мьютекс на методы передачи файлов (например, синхронизация на объекте), чтобы избежать переполнения содержимого файлов? Как несколько AsyncTask могут работать одновременно в некоторых версиях Android? Я признаю, что я более Java, чем разработчик Android, поэтому простите меня, если есть другая защита от этого ... – drrob

+0

Если сокет используется более чем одним потоком, вам определенно нужна защита. Было бы даже лучше разработать решение таким образом, чтобы полностью исключить эту ошибку, и не разрешать совместное использование сокета разными потоками. – Joni

Смежные вопросы