从android中的socket输入流中读取错误的字节数

时间:2012-12-12 06:32:32

标签: android sockets

我编写了以下代码来读取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字节。

我做错了什么?我错过了什么? 我是否需要关闭套接字?这是我在关闭应用时更喜欢做的事情,而不是在我展示的代码中。

ANDROID APP CODE:

    @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;
    }

2 个答案:

答案 0 :(得分:0)

很难说你什么时候不在那里:) 但我会做以下事项:

  1. 一次逐步读取更少的字节并构建完整的字节 来自这个较小块的字节数组
  2. 调试这些行并准确查看“bug”出现的时间

答案 1 :(得分:0)

read方法不读取整个流。它只读取流缓冲区中当前可用的字节。

要从流中读取完整数据,您可以使用readFully() method或使用以下代码从流中读取完整数据:

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();