我知道存在类似的问题,但我还没有找到适合我的问题的问题。我有一台 Android 设备(API 15 - Android 版本 4.0.4)和一台运行 Arch Linux 的 Linux 机器。这个想法是在服务器(C 程序)和客户端(Android 应用程序)之间创建连接,以便我可以交换文件。此外,服务器支持并行连接并需要身份验证。 Android应用程序必须创建3个到服务器的连接(使用3个不同的端口,这意味着3个AsyncTask-s运行多线程)..其中两个用于并行后台进程,1个用于实际文件传输。我创建了一个在模拟器(Android KitKat OS)上运行良好的代码,但是在我自己的手机上测试时它不起作用。我将发布我的代码,如果可能的话,我希望得到您的一些建议。谢谢。
这是在 Android 设备上运行的代码...BUFFSIZE 是1024,它是一个全局变量。 我尝试将其设置为许多值,但没有一个对我有用。 filesize 在代码的前面设置,并且始终具有正确的值,因此不必担心:)
InputStream is = socket.getInputStream();
FileOutputStream fs = new FileOutputStream(target);
int u;
byte[] jj = new byte[BUFFSIZE];
long overall = 0, percent = 0;
try {
while (overall < filesize && mRun) {
u = is.read(jj, 0, BUFFSIZE);
if (u == -1) break;
fs.write(jj, 0, u);
overall += u;
percent = overall*100/filesize;
}
fs.flush();
fs.close();
is.close();
socket.close();
} catch (IOException ex) {
// There were no exceptions while testing
// There is some code here that deals with the UI
// which is not important
}
这是 C 代码...
for (;;)
{
/* First read file in chunks of BUF_SIZE bytes */
unsigned char buff[BUFFER]={0};
int nread = fread(buffer,1,BUFFER, input);
printf("Bytes read %d \n", nread);
/* If read was success, send data. */
if(nread > 0)
{
printf("Sending \n");
write(sockfd, buffer, nread);
}
/*
* There is something tricky going on with read ..
* Either there was error, or we reached end of file.
*/
if (nread < BUFFER)
{
if (feof(input))
printf("End of file\n");
if (ferror(input))
printf("Error reading\n");
break;
}
}
我已经多次测试了这段代码,甚至使用 telnet 也运行得很好。但我不确定 Java 代码。
那么,为什么它不起作用呢?嗯,到目前为止我所知道的是一些文件已损坏。假设我传输一个大小为 4MB 的 mp3 文件,则将发送 3.99 个,而其余的 0.01 个将无缘无故地丢失在文件中间的某个位置!当您播放损坏的 mp3 时,您会发现某些部分(例如每 10 秒)变得“不正常”。就像有一个小噪音然后被跳过一样。生成的文件比原始文件短约 10 000 字节(但这取决于实际文件大小。您总是会丢失文件的一小部分,这意味着 while 循环永远不会完成 - 下载过程永远不会完成,因为套接字正在阻塞,客户端最终会等待更多从未收到的字节)..我相信发生的情况是,从 1024 字节长的缓冲区中,有时会使用大约 1000 字节,而不是完整的 1024 缓冲区size,这会导致丢失 24 个字节。我并不是说这些是实际数字,但这只是我脑海中发生的事情;我对此可能是错的。我无法与您分享整个代码,因为它真的很长,所以我决定使用处理下载过程的函数。
最佳答案
read 方法不填满整个缓冲区是完全可以的。该方法返回读取的字节数。您甚至可以将该值分配给变量:
u = is.read(jj, 0, BUFFSIZE);
但随后您只需检查 u
是否为 -1
即可确定何时停止读取。来自文档:
The number of bytes actually read is returned as an integer.
这意味着您的字节数组的最大长度为 1024 字节,但并非每次读取
时都会填充所有这些字节。当然不会,否则只有当您的输入流包含 1024 字节的 exakt 倍数时,这才有效。
另外:存在一种称为调试
的东西。检查 mp3 文件等二进制数据可能很困难,因此请尝试在传输文本文件时进行调试。
关于java - 使用 TCP 在 Java(Android 客户端)和 C(PC 服务器 - Linux)之间传输文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38765723/