2015-08-15 119 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