在Android中使用Socket接收文件

时间:2016-08-12 15:23:02

标签: android sockets android-studio

我想在服务器和客户端之间传输文件,Server是一个用Dely编写的Windows程序,用Indy和Client是一个Android

这是我从socket读取的客户端代码:

...
InputStream IS = S.getInputStream();
byte[] FBytes = new byte[FileSize];
FileOutputStream FOS = new FileOutputStream(TempFile);
BufferedOutputStream BOS = new BufferedOutputStream(FOS);
int BytesRead = IS.read(FBytes);
int CurrProgress = BytesRead;
do {
    Log.d("DOWNLOAD", "BytesRead2 = " + Integer.toString(BytesRead));
    if(CurrProgress < FBytes.length) {
        Log.d("DOWNLOAD", "prog < BytesRead" );
        BytesRead = IS.read(FBytes);
        if (BytesRead > 0)
          CurrProgress += BytesRead;
        B.clear();
        B.putInt("ProgValue", CurrProgress);
        Msg.what = MSG_FILE_PROGRESS;
        Hdlr.dispatchMessage(Msg);
        Log.d("DOWNLOAD", "BytesRead = " + Integer.toString(BytesRead));
    }
} while (BytesRead > 0);
Log.d(TAG, "Download Loop Finished");

文件将下载,但问题是下载文件的大小低于原始文件,并且套接字读取命令保留在上次读取。换句话说,文件已被下载,但CurrProgress低于FBytes.length,所以循环执行一次以上,程序挂起读命令,因为没有更多数据从服务器发送

我已经使用Windows程序测试了服务器,服务器代码没有问题

我已经测试了很多这样的方法,但没有机会:

int BytesRead = IS.read(FBytes, 0, FBytes.length);
int CurrProgress = BytesRead;
do {
    Log.d("DOWNLOAD", "BytesRead2 = " + Integer.toString(BytesRead));
    if(CurrProgress < FBytes.length) {
        Log.d("DOWNLOAD", "prog < BytesRead" );
        BytesRead = IS.read(FBytes, CurrProgress, (FBytes.length - CurrProgress));
    ...
  • FileSize值是正确的,在读取文件字节之前来自服务器作为字符串值

出了什么问题?!,谢谢......

编辑:

完整的代码执行许多其他工作,但读取文件的代码是这样的:

public void Run()
    {
        Running = true;

        try{
            try{
                InetAddress ServerAddr = InetAddress.getByName(SERVER_IP);
                S = new Socket(ServerAddr, SERVER_PORT);
                Log.d(TAG, "Connecting ...");
                Out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(S.getOutputStream())), true);
                In  = new BufferedReader(new InputStreamReader(S.getInputStream()));
                switch (Job) {
                    ...
                    }
                    case GetFile: {
                        this.SendMessage(Cmd);
                        response = In.readLine();
                        if(response.equals("1"))
                        {
                            Hdlr.sendEmptyMessage(MSG_SERVER_ACCEPT);

                            response = In.readLine();
                            int FileSize = Integer.parseInt(response);

                            if (context.getFilesDir().getFreeSpace() < 3 * FileSize)
                            {
                                Hdlr.sendEmptyMessage(MSG_ERROR_FREESPACE);

                                Log.d(TAG, "There is no Free Space !");
                            }
                            else {

                                final Message Msg = new Message();
                                final Bundle B = new Bundle();
                                B.putInt("FSize", FileSize);
                                Msg.what = MSG_FILE_SIZE;
                                Msg.setData(B);
                                Hdlr.dispatchMessage(Msg);

                                try {
                                    File TempDir, TempFile, MainDir, MainFile;

                                    switch(FileType)
                                    {
                                        case 2 :
                                            TempDir = new File(context.getCacheDir(), "TempMP3");
                                            if(!TempDir.exists()) {
                                                TempDir.mkdir();
                                            }
                                            TempFile = new File(TempDir, Integer.toString(FileIndex) + ".mp3");
                                            if(TempFile.exists()) {
                                                TempFile.delete();
                                            }
                                            break;
                                        default :
                                            TempDir = new File(context.getCacheDir(), "TempLevel");
                                            if(!TempDir.exists()) {
                                                TempDir.mkdir();
                                            }
                                            TempFile = new File(TempDir, Integer.toString(FileIndex) + ".zip");
                                            if(TempFile.exists()) {
                                                TempFile.delete();
                                            }
                                    }

                                    InputStream IS = S.getInputStream();
                                    byte[] FBytes = new byte[4096];

                                    FileOutputStream FOS = new FileOutputStream(TempFile);
                                    BufferedOutputStream BOS = new BufferedOutputStream(FOS);
                                    int BytesRead = 0;
                                    int CurrProgress = 0;

                                    do {
                                        Log.d("DOWNLOAD", "prog < BytesRead" );
                                        BytesRead = IS.read(FBytes, 0, FBytes.length);
                                        BOS.write(FBytes, 0, BytesRead);

                                        if (BytesRead > 0)
                                            CurrProgress += BytesRead;

                                        B.clear();
                                        B.putInt("ProgValue", CurrProgress);
                                        Msg.what = MSG_FILE_PROGRESS;
                                        Hdlr.dispatchMessage(Msg);

                                        Log.d("DOWNLOAD", "BytesRead = " + Integer.toString(BytesRead));
                                    } while (CurrProgress < FileSize);

                                    Log.d(TAG, "Download Loop Finished");
                                    if (CurrProgress != FBytes.length) {
                                        BOS.close();

                                        Hdlr.sendEmptyMessage(MSG_ERROR_FILESIZE);
                                        Log.d(TAG, "File Size Problem");
                                    } else {
                                        BOS.close();
                                        Log.d(TAG, "File Downloaded successfully, Preparing to Unzip ... ");
                                        try {

                                            MainDir = new File(context.getFilesDir(), "Levels");
                                            if(!MainDir.exists())
                                            {
                                                MainDir.mkdir();
                                            }

                                            File LevelDir = new File(MainDir, Integer.toString(FileIndex));
                                            if(!LevelDir.exists())
                                            {
                                                LevelDir.mkdir();
                                            }
                                            else
                                            {
                                                LevelDir.delete();
                                            }

                                            FileInputStream fin = new FileInputStream(TempFile);
                                            ZipInputStream zin = new ZipInputStream(fin);
                                            ZipEntry ze = null;
                                            while ((ze = zin.getNextEntry()) != null) {
                                                MainFile = new File(LevelDir, ze.getName());
                                                FileOutputStream FOut = new FileOutputStream(MainFile);
                                                for (int c = zin.read(); c != -1; c = zin.read()) {
                                                    FOut.write(c);
                                                }

                                                zin.closeEntry();
                                                FOut.close();
                                            }
                                            zin.close();
                                        } catch (Exception e) {
                                            Log.d(TAG, "Unzip Error : ", e);
                                        }
                                    }
                                } catch (Exception E) {
                                    Err = 1;
                                    Log.d(TAG, "Get File Error : ", E);
                                }
                            }
                        }
                        else
                        {
                            if (Listener != null)
                            {
                                Listener.callbackMessageReceiver(response);

                                Hdlr.sendEmptyMessage(MSG_ERROR_SERVER);
                            }
                        }

                        break;
                    }
                    ...
                }

            }catch (Exception e)
            {
                Hdlr.sendEmptyMessage(MSG_ERROR_SEND);
                Log.d(TAG, "Connect Error : ", e);
            }
            finally{
                if(Out != null) {
                    Out.flush();
                    Out.close();
                }
                if(In != null)
                {
                    In.close();
                }

                S.close();
                Log.d(TAG, "Err Value is : " + Integer.toString(Err));
                if(Err == 0)
                {
                    Hdlr.sendEmptyMessage(MSG_SUCCESS);
                }

                Log.d(TAG, "Sending Ends");
            }
        }catch (Exception E){
            Log.d(TAG, "Error : ", E);

        }
    }

CurrProgress低于FileSize(差值大约为4或5 KB),而while循环在读取命令时挂起!

1 个答案:

答案 0 :(得分:0)

问题解决了,我会将其作为答案发布,这可能是有用的

问题是服务器在发送FileSize后立即发送文件,我认为BufferedReader获取File的一些字节,因此IS给出的字节大小低于FileSize,例如Server:

...
WriteLn(FileSize);
Write(FileStream);
...

现在,Server首先发送FileSize,然后等待来自客户端的响应,在检查客户端的freespace后,它向服务器发送Ready响应,然后Server发送文件流,例如:

...
WriteLn(FileSize);
Response := ReadLn();
if Response = "READY" then
 Write(FileStream);
...

客户端中的代码如下:

...
BufferedInputStream BIS = new BufferedInputStream(S.getInputStream());
In  = new BufferedReader(new InputStreamReader(S.getInputStream()));
...
response = In.readLine();
int FileSize = Integer.parseInt(response);
if (context.getFilesDir().getFreeSpace() < 3 * FileSize)
{
    Hdlr.sendEmptyMessage(MSG_ERROR_FREESPACE);
    Log.d(TAG, "There is no Free Space !");

    this.SendMessage("NOT_READY");
}
else {
    ...
    try {
        this.SendMessage("READY");

        byte[] FBytes = new byte[8192];
        FileOutputStream FOS = new FileOutputStream(TempFile);
        BufferedOutputStream BOS = new BufferedOutputStream(FOS);
        int BytesRead = 0;
        int CurrProgress = 0;
        while (CurrProgress < FileSize){
            Log.d("DOWNLOAD", "Available : " + Integer.toString(BIS.availabl
            BytesRead = BIS.read(FBytes, 0, FBytes.length);
            BOS.write(FBytes, 0, BytesRead);
            if (BytesRead > 0)
                CurrProgress += BytesRead;
            B.clear();
            B.putInt("ProgValue", CurrProgress);
            Msg.what = MSG_FILE_PROGRESS;
            Hdlr.dispatchMessage(Msg);
            Log.d("DOWNLOAD", "BytesRead = " + Integer.toString(BytesRead));
        }

没有问题,一切正常

相关问题