마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

JavaServer 와 Android Socket 통신으로 파일전송중 문제가있습니다. [closed]

0 추천

JavaServer 에서 Android 로 여러개의 파일을 전송을 하고 싶어서

코딩을하고 있습니다. 하지만 파일은 전송되지만 한가지 문제가 발생하는데

에러는 나지 않고 정상적으로 소켓통신은 작동하지만

JavaServer에서 보내고자하는 파일 sample1.txt(674kb) , sample2.txt(1300kb)를 전송하면

Android Client에서는 sample1.txt(1974kb), sample2.txt(0kb) 이런식으로 하나의 파일에

모든 값이 저장됩니다. 소스에서 어디가 문제인지 잘 이해가 되지 않습니다...

JavaServer 소스입니다.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

public class MultifileTransferServer {
    public ServerSocket serv;
    public Socket sock;

    BufferedInputStream bis = null;
    DataInputStream dis = null;
    DataOutputStream dos = null;

    ArrayList<String> fileNames = new ArrayList<String>();
    ArrayList<File> files = new ArrayList<File>();


    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try
        {
            System.out.println(InetAddress.getLocalHost().getHostAddress());
        }catch(UnknownHostException e)
        {
            e.printStackTrace();
        }
        MultifileTransferServer server = new MultifileTransferServer(5000);
    }

    public MultifileTransferServer(int port)
    {
        try 
        {
            fileNames.add("sample1.txt");
            fileNames.add("sample2.txt");

            for(String fileName : fileNames)
            {
                files.add(new File("D:/TestTest/"+fileName));
            }

            this.serv = new ServerSocket(port);
            System.out.println("Server Started...~~");
            while(true)
            {
                this.sock = this.serv.accept();
                try
                {   
                    System.out.println("Client Accept....!!");

                    dis = new DataInputStream(new BufferedInputStream(sock.getInputStream()));
                    dos = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream()));


                    dos.writeInt(fileNames.size());
                    int readSize = 0;

                    int n = 0;
                    byte[]buf = new byte[4092];
                    byte[] done = new byte[3];
                    String str = "    ";
                    done = str.getBytes();

                    for(int i=0;i<fileNames.size();i++)
                    {
                        System.out.println("Start File Trans "+ i);


                         FileInputStream fis = new FileInputStream(files.get(i));
                            while((n =fis.read(buf)) != -1){
                                dos.write(buf,0,n);
                                System.out.println(n);
                                dos.flush();
                            }

                            dos.write(done,0,3);
                            dos.flush();

                                                }

                }catch(Exception e)
                {
                    e.printStackTrace();
                }finally
                {
                    try 
                    {
                        if(bis != null) bis.close();
                        if(dos != null) dos.close();
                        if(dis != null) dis.close();
                    } 
                    catch (Exception e2) 
                    {
                        // TODO: handle exception
                        e2.printStackTrace();
                    }
                }
            }

        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

 

Android Client 소스입니다.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.io.IOException;
import java.net.Socket;

public class MainActivity extends AppCompatActivity {

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

        final String testDir = getApplicationContext().getCacheDir().toString();

        new Thread()
        {
            public void run()
            {
                String ServerIP = "192.168.0.10";
                int port = 5000;
                SocketConnect(ServerIP,port);
            }
        }.start();
    }

    public void SocketConnect(String ServerIP, int port)
    {
        try
        {
            Socket connection = new Socket(ServerIP, port);
            MultiFileTransferClient.Client(connection);

        }catch(IOException e)
        {
            e.printStackTrace();
        }
    }
}

import android.os.Environment;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Writer;
import java.net.Socket;

public class MultiFileTransferClient {

    public static void Client(Socket sock)
    {

        BufferedOutputStream bos = null;
        ObjectOutputStream oos = null;
        DataInputStream dis = null;
        DataOutputStream dos = null;
        int fileTransferCount = 0;
        long fileTransferSize = 0;
        int readBufLength = 0;
        File copyFile = null;

        String[] TestFileName = new String[2];

        TestFileName[0] = "sample1.txt";
        TestFileName[1] = "sample2.txt";

        try {

            dis = new DataInputStream(new BufferedInputStream(sock.getInputStream()));
            dos = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream()));

            String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath();

            try
            {

                fileTransferCount = dis.readInt();
                int n = 0;
                byte[]buf = new byte[4092];

                for(int i=0; i< fileTransferCount ;i++)
                {
                    Log.d("Test","Receiveing file : " + TestFileName[i]);
                    copyFile = new File(TestFileName[i]);
                    FileOutputStream fos = new FileOutputStream(sdcard+"/"+copyFile,false);

                    while((n = dis.read(buf)) != -1 && n!=3 ){
                        fos.write(buf,0,n);
                        fos.flush();
                    }
                    fos.close(); 
                }

            }
            catch (Exception e)
            {
                // TODO: handle exception
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally
        {
            try
            {
                if(dis != null) dis.close();
                if(dos != null) dos.close();
                if(sock != null) sock.close();
            }
            catch (Exception e)
            {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
    }
}

그리고 혹시 반대로 Android Client 에서 JavaServer로 파일을 전송할떄도 위의 소스를 이용해도

되는건가요?

질문을 종료한 이유: 해결되었습니다.! 애당초에 저렇게 하지않고 좀더 간편한 방법이있었는데 너무 복잡하게 생각하였군요 모두 답변 감사합니다!
쌈빱 (280 포인트) 님이 2016년 5월 2일 질문
쌈빱님이 2016년 5월 2일 closed

2개의 답변

+1 추천
파일을 보낼때 처음에 파일 길이 값을 보내서

그걸 기준으로 들어오는 정보를 길이만큼 구분해서 저장을 해야합니다.

자동으로 2파일로 저장되진 않습니다.
이라슈 (8,770 포인트) 님이 2016년 5월 2일 답변
writeLong 를 통하여 파일 길이를 보내려 했는데
처음 파일 값은 정상적으로 들어가지만
2번쨰 파일 부터는 이상한 값이 들어가지더라구요;;
그래서 FileInputStream,FileOutputStream을 통하여
파일 끝까지 읽어서 보내면서 done을 통하여 파일의 EOF를 구분해 주려 했던건데 소스상 어디가 문제가 있는건가요?
+1 추천
두개를 연속으로 보내면 받는쪽에서 구분을 안합니다.

보낼때 하나만 보낸다음 받는쪽에서 하나 다 받고 파일 닫고나면 ok 사인 보내고

서버에서 ok 사인 받으면 다음 파일 보내고 이런식으로 해보세요
안드잘하고싶 (3,310 포인트) 님이 2016년 5월 2일 답변
dos.write(done,0,3);
dos.flush();
done의 값인 "    "(스페이스 4번)
을 통하여 구분지어 줄려 했는데
JavaServer->Android Client는 간간히 정상적으로 파일2개가 들어올 떄가 있는데
AndroidClient -> JavaServer는 하나의 파일로만 오는데
그럼 저런식의 사인인 아닌 다른씩으로 사인을 보내야 한다는 말씀이신가요?
소켓에서 getOutputStream()해서 이걸로 서버에 특정 메시지를 println 해보세요
그리고 서버에서 메시지를 기다리다가 해당 메시지가 오면 다음 파일을 보내는식으로 하면 됩니다.
...