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

안드로이드 소켓통신 데이터 전송 오동작

0 추천
임베디드 보드에서 mp3파일이나 wav파일을 읽어서 tcp를 통해서 스마트폰으로 전송받는 앱을 만들고있습니다 c에서는 다음과 같이

struct filestate{
char state[5];
int size;
char data[500]
};
512바이트로 구성되었구요 fread를 통해서 파일을 읽고 write함수를 통해서 전송을 했습니다

state의 경우 파일의 실제 데이터임을 알려주는 정보를 넣고 size는 지금 전송한 데이터의 사이즈를 어디까지 읽어야되는 알려주는 정보를 닮았고 실제 데이터는 500바이트 짜리 배열에 담았습니다

안드로이드에 파일 수신을 위한 스레드코드입니다

보내는 쪽에서는 분명히 데이터를 제대로 보내준거 같은데 받을때 뭔가 이상해서 state쪽 로그를 찍어봤는데 실제 파일의 정보임을 알려주는 state의 값인 Fbody의 값이 처음에 몇번정도만 찍히고 나머지는 제가 보내주지 않은 이상한 값이 찍히는데 값이 뒤죽 박죽으로 들어오는것도 가능한건가요? 이경우 어떻게 해결해야 할지 궁금합니다

class FReceiveThread extends Thread
{
        boolean isLoop = true;

        public void setIsLoop(boolean isLoop)
        {
            this.isLoop = isLoop;
        }

        @Override
        public void run()
        {
            ServerSocket serverSocket = null;
            try
            {

                Log.i("SocketService", "Start Freceive");

                String state;
                int Fsize = 0;
                int Bsize = 0;
                int j = 0;
                serverSocket        = new ServerSocket(8005);
                Socket socket       = serverSocket.accept();
                //BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                DataInputStream in  = new DataInputStream(socket.getInputStream());
                FileOutputStream fos = null;
                byte[] dataBuff     = new byte[512];
                byte[] stateBuff    = new byte[5];
                byte[] sizeBuff     = new byte[4];
                byte[] BodyBuff     =new byte[500];

                while (isLoop)
                {

                    Log.i("Freceive", "TopWhile");

                    in.read(dataBuff,0,dataBuff.length);
                    System.arraycopy(dataBuff,0,stateBuff,0,5);
                    state           = new String(stateBuff);

                    Log.i("Freceive", "state:" +state);

                    if(state.equals("Finfo"))
                    {
                        //Log.i("Freceive", "if(Finfo)" );

                        System.arraycopy(dataBuff,8,sizeBuff,0,4);

                        //Log.i("FreceiveSizeBuff", ""+sizeBuff[0]);
                        //Log.i("FreceiveSizeBuff", ""+sizeBuff[1]);
                        //Log.i("FreceiveSizeBuff", ""+sizeBuff[2]);
                        //Log.i("FreceiveSizeBuff", ""+sizeBuff[3]);

                        Fsize = ((sizeBuff[3]&0xff) << 24) | ((sizeBuff[2]&0xff) << 16) | ((sizeBuff[1]&0xff) << 8) | (sizeBuff[0]&0xff);
                         //int* psize = (intsizeBuff;
                         //Fsize=getInt(sizeBuff);

                        File StoreDir                   = new File(AppDirectory);

                        if( !StoreDir.exists() )
                        {
                            StoreDir.mkdirs();
                        }

                        Log.i("Freceive", ""+Integer.toString(Fsize));
                       
                        file = new File(AppDirectory+"/"+messege);

                        fos = new FileOutputStream(file);

                    }
                    else if(state.equals("Fbody"))
                    {
                        System.arraycopy(dataBuff,8,sizeBuff,0,4);

                        //Log.i("FreceiveSizeBuff", ""+sizeBuff[0]);
                        //Log.i("FreceiveSizeBuff", ""+sizeBuff[1]);
                        //Log.i("FreceiveSizeBuff", ""+sizeBuff[2]);
                        //Log.i("FreceiveSizeBuff", ""+sizeBuff[3]);

                        Bsize = ((sizeBuff[3]&0xff) << 24) | ((sizeBuff[2]&0xff) << 16) | ((sizeBuff[1]&0xff) << 8) | (sizeBuff[0]&0xff);
                        Log.i("Freceive", ""+Integer.toString(Bsize));
                        System.arraycopy(dataBuff,12,BodyBuff,0,500);
                        fos.write(BodyBuff,0,Bsize);
                        //fos.flush();
                        j +=Bsize;
                    }
                    else if(state.equals("Fend!"))
                    {
                        Log.i("FileE","Fclose"+j);
                        j = 0;
                        //Log.i("FileE","Fclose"+j);
                        fos.close();
                    }

                }

            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
계절풍M (270 포인트) 님이 2017년 7월 16일 질문

1개의 답변

0 추천

1. TCP 연결이면 뒤집히지는 않을 겁니다.

2. 사이즈가 512가 맞나요? char 5, int 4, data 500 이니 509 사이즈 인 듯 한데요..

컴파일러에 따라 빈 구조체를 2의 배수로 채워주는게 있긴 하지만.. 파일로 쓰고 읽다보면 꼬이지 않는다는 보장이 없으니.. 확실하게 하기 위해 data를 503 으로 올리던지 패딩 3byte를 붙여 주셔야 할 듯 합니다.

3.  소켓 버퍼 상태에 따라 in.read 에서 read한 사이즈가 원하신 512가 나오지 않을 수도 있습니다. 

이 경우 512단위로 읽어지도록 재시도 시켜 주셔야 합니다.

 

익명사용자 님이 2017년 7월 17일 답변
2017년 7월 17일 수정
padding 까지 계산해서 512로 만들어 준 크기이구요 log.i로 read함수 리턴형 받아보니 데이터가 512개가 아닌 그보다 적은수를 받아서 그런거 같습니다 그래서 스트림을 읽어서 버퍼로 값을 옮기기 전에 available 함수의 리턴값이 512보다 적을때 까지 while루프로 기다리니 정상적으로 파일도 수신됩니다 감사합니다
데이터에 바이트코드로  0 (Null) 이 있으면 512로 보내도 0까지만 수신하여 반환합니다. 그 다음 Read에 다음 인덱스부터 데이터를 로드합니다.
문자열이 아닌 바이트코드 데이터를 송수신할때에는 패킷 종료 코드를 추가하셔서 수신 패킷이 끝에 도달했는지 확인하시는게 좋습니다.
...