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

当你不在那里时很难说:)
但我会做以下事情:

  1. 一次读取逐渐减少的字节,并从这些较小的块中构建完整的字节数组
  2. 调试这些行并准确查看“错误”何时出现
于 2012-12-12T21:41:01.963 回答
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 回答