1

ソケットを介して Android アプリが受信したデータ (具体的にはファイル) を読み取るために、次のコードを作成しました。

    DataInputStream inputStream = new DataInputStream(socket.getInputStream());
    byte[] buffX = new byte[30054];
    int k = inputStream.read(buffX,0,30054);

C で記述されたコードから送信しているデータが 30054 バイトのファイルであることはわかっています。

問題は、変数 k が 2000 未満であることです。つまり、送信されたすべてのファイルを読み取れないか、ファイルの一部が破棄されました。レシーバー バッファーのサイズ (Android アプリ内) が 80kB を超えていることを既に確認しました。

サイズが 1662 バイトのファイルで同じコードをテストしたところ、予想どおり、変数 k は 1662 バイトに等しくなりました。

私は何を間違っていますか?私は何が欠けていますか?ソケットを閉じる必要がありますか? これは、コードを表示している間ではなく、アプリを閉じるときに行うことを好みます。

アンドロイドアプリコード:

    @SuppressLint("HandlerLeak")
    public class DisplayNewActivity extends Activity {
        ...
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.mainnewact);
            mHandler = new Handler() { // used to show the number of bytes that were read
                @Override
                public void handleMessage(Message msg) {
                    int d2 = (Integer)msg.obj;
                    commentS.setText(Integer.toString(d2));
                }
            }
            ...
            cThread = new Thread(new ClientThread()); // used to start socket connection 
            rThread = new Thread(new RcvThread()); // used to read incoming packages once the socket has been connected
            cThread.start();
        }

        public class ClientThread implements Runnable {
            public void run() {
                try {
                      ...
                      socket = new Socket(serverIpAddress, Integer.parseInt(serverPort));
                      rThread.start();
                      while (connected) { };
                      ...
                } catch (Exception e) { startActivity(intentback);}
            }
        }

        @SuppressLint("HandlerLeak")
        public class RcvThread implements Runnable {
            public void run() {
                while (connected) {
                    try {
                        DataInputStream inputStream = new DataInputStream(socket.getInputStream());
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        byte[] imBytes = new byte[31000];
                        int numRead = 0;
                        while ((numRead = inputStream.read(imBytes)) >= 0) {
                            baos.write(imBytes,0,numRead);
                        }
                        byte[] imageInBytes = baos.toByteArray();
                        int k = imageInBytes.length;
                        Message msg = new Message();
                        msg.obj = k;
                        mHandler.sendMessage(msg);
                    } catch (Exception e) {
                        Log.e("SocketConnectionv02Activity", "C: ErrorRCVD", e);
                    }
                }
            }
        }
    }    

C コード:

    ...
    #include <sys/sendfile.h>
    ...
    int main(int argc, char *argv[]){
        int sockfd, newsockfd, portno;
        socklen_t clilen;
        struct sockaddr_in serv_addr, cli_addr;
        int fdfile;
        struct stat stat_buf;
        off_t offset = 0;
        int img2send = 1;
        char buffer[256];
        int closeSocket = 0;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) {error("ERROR opening socket"); exit(1);}
        bzero((char *) &serv_addr, sizeof(serv_addr));
        portno = 55000;
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        serv_addr.sin_port = htons(portno);
        if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { 
            error("ERROR on binding");
            close(sockfd);
            exit(1);
        }
        listen(sockfd,1);
        clilen = sizeof(cli_addr);
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if (newsockfd < 0) {
            error("ERROR on accept");
            close(sockfd);
            exit(1);
        }
        while (closeSocket == 0) {
            if (img2send == 1) { // interchange the file that is sent through the socket
                 fdfile = open("/home/gachr/Desktop/CamaraTest/fig1bmp.bmp", O_RDONLY); 
                 img2send = 2;
            } else {
                 fdfile = open("/home/gachr/Desktop/CamaraTest/fig2bmp.bmp", O_RDONLY);
                 img2send = 1;
            }
            if (fdfile == -1) {
                 close(sockfd); 
                 close(newsockfd);
                 exit(1);
            } else {
                 fstat(fdfile, &stat_buf);
                 offset = 0;
                 n = sendfile(newsockfd, fdfile, &offset, stat_buf.st_size);
                 if (n == stat_buf.st_size) { printf("Complete transfering file\n"); }
                 close(fdfile);
            }
            sleep(5);
            bzero(buffer,256);
            n = recv(newsockfd,buffer,1,MSG_DONTWAIT); // to close the socket from the Android app, which is working
            if (n > 0) {
                  if (buffer[0] == 48){ closeSocket = 1;}
            }
        }
        close(newsockfd);
        close(sockfd);
        return 0;
    }
4

2 に答える 2

0

readメソッドは、フルストリームを読み取りません。ストリームバッファで現在使用可能なバイトのみを読み取ります。

ストリームから完全なデータを読み取るには、readFully()メソッドを使用するか、次のコードを使用してストリームから完全なデータを読み取ります。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes = new byte[8192];

int numRead = 0;
while ((numRead = inputStream.read(bytes)) >= 0) {
    baos.write(bytes,0,numRead);
}

byte[] fileData = baos.toByteArray();
于 2012-12-13T07:31:24.003 に答える
0

あなたがそこにいないときを言うのは難しいです:)
しかし、私は次のことをします:

  1. 一度に徐々に少ないバイトを読み取り、この小さなチャンクからバイトの完全な配列を構築します
  2. これらの行をデバッグし、「バグ」がいつ表示されるかを正確に確認します
于 2012-12-12T21:41:01.963 に答える