java - 使用 TCP 在 Java(Android 客户端)和 C(PC 服务器 - Linux)之间传输文件

标签 java android c tcp file-transfer

我知道存在类似的问题,但我还没有找到适合我的问题的问题。我有一台 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/

相关文章:

java - 安卓 GPS 错误

c# - 如何制作自己的图形界面?

java - 有没有办法使用或运算符 ||在 java 中的 char 上?

java - 在 Google App Engine 上部署 Spring Boot 应用程序时出错

java - BaseAdapter 的relativelayout addRule 工作得不太好

Android:如何覆盖 Google map 上的指南针操作

c - 在使用套接字进行进程间通信期间,strcmp 的行为似乎很奇怪

java - Java 代码在单个线程中的执行是否保证是顺序的?

java - 在不同条件的循环内模拟相同方法获得相同结果

java - Java中有类似JavaScript的 "prototype"的东西吗?