2015-08-15 117 views
0

我正在開發一個應用程序,並且我想使用套接字將文件從計算機傳輸到手機。我能夠傳輸一個文件,但是當我想傳輸多個文件時,它們堆積如山。以下是該程序的工作原理:通過套接字傳輸多個文件

  1. 我從計算機上使用Robot獲得屏幕截圖。
  2. 我把它保存爲Send.jpg。
  3. 我發送圖片。比方說,例如它的大小是1 MB。
  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"); 
      } 
     } 
    } 

} 

客戶端(電話):

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中同時運行?我承認我比Android開發人員更多的Java,所以請原諒我,如果有其他保護措施... – drrob

+0

如果套接字被多個線程使用,您肯定需要保護。以一種完全避免這種錯誤的方式來設計解決方案會更好,並且不允許套接字被不同的線程共享。 – Joni