我编写了以下代码来读取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;
}
答案 0 :(得分:0)
很难说你什么时候不在那里:)
但我会做以下事项:
答案 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();