前段时间写了一篇关于int这些基本数据类型在java和linux-c上传的问题。因为我的目标是做一个android手机拍照上传的项目,服务器是linux-c,所以上传照片是关键的。
但是每次传图片总是大不开,后来用ultraedit看了下里面的16进制数发现前面都对的,就是最后的几行全部都是零。先不说了,代码贴了先。
public boolean send(File file, ProgressBar pb) {
byte[] buf = new byte[1024];
try {
FileInputStream fis = new FileInputStream(file);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
int size = fis.available();
System.out.println("size=" + size);
send(size);
int len;
while((len = fis.read(buf)) > 0) {
dos.write(buf, 0, len);
dos.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
这里关于socket连接的代码就不贴了,就贴个socket传图片的代码。因为dos不能关掉,以后还要传东西,为了防止服务器把其他数据也当做是图片收了,我先发了个文件大小size过去,之后用一个循环读一个buf数组传一个。
接下来是服务器端的代码,也只贴接收图片的函数
//接收一个文件,参数是连接ID和保存的路径,以覆盖方式储存,如接收正常返回1,不正常返回-1
int receiveFile(int connfd, char* path) {
int size, n;
n = recv(connfd, &size, sizeof(int), 0);
if (n == -1 || n == 0) {
perror("接收错误!\n");
return -1;
}
printf("size = %d\n", size);
char buffer[1024];
bzero(buffer, 1024);
int length = 0, receive = 0;
int write_length;
FILE* fp = fopen(path, "wb");
//每次接收1024个字节,直到剩下的字节数不到1024为止
while (size >= 1024) {
length = recv(connfd, buffer, 1024, 0);
if (length <= 0) {
printf("Recieve Data Failed!\n");
return -1;
}
write_length = fwrite(buffer, sizeof(char), length, fp);
receive += write_length;
bzero(buffer, 1024);
size -= length;
}
//不断已剩下字节数为为单位接收,直到全部接收为止
while (size > 0) {
length = recv(connfd, buffer, size, 0);
if (length <= 0) {
printf("Recieve Data Failed!\n");
pthread_cancel()
}
write_length = fwrite(buffer, sizeof(char), length, fp);
receive += write_length;
printf("receive %d/%d bytes\n", write_length, size);
size -= length;
}
fclose(fp);
printf("receive file over!\n");
return 1;
}
这里特别要讲的是第二个循环,我前面出现的最后接收到全都是0的问题就在这里。原来我只接收一次,没有重新循环,结果发现你在recv函数里写的size只是个最大的接收量,事实上是不一定的。我测试了很多次发现基本都需要两次才能将剩下的数据接收完,当然,有的时候一次就成功了。所以原来没有这个循环的情况下我将压根没有收好的数组写到了文件里当然就打不开了。
希望我的教训能帮到遇到同样问题的朋友。自学的路是艰难的,贵在坚持啊。