【问题标题】:Java network file transfer problemJava网络文件传输问题
【发布时间】:2026-01-09 19:35:01
【问题描述】:

我正在编写一个可以测量本地网络速度的小型 Java 程序。这是我第一次使用套接字,但我已经编写了一个可以工作的程序。唯一的问题是测量结果远非准确(太低了)。

这是服务器代码:

ServerSocket servsock = new ServerSocket(13267);
while (true) {
    System.out.println("Waiting...");

    Socket sock = servsock.accept();
    System.out.println("Accepted connection : " + sock);

    File myFile = new File("test.txt");
    FileInputStream in = new FileInputStream(myFile);
    OutputStream out = sock.getOutputStream();

    int bytes = 0;
    byte[] buffer = new byte[8192];
    int len;

    while ((len = in.read(buffer)) > 0) {
        out.write(buffer, 0, len);
        bytes += len;
    }

    System.out.println("Transfer completed, " + bytes + " bytes sent");

    out.flush();
    sock.close();
}

这是客户端代码:

Socket sock = new Socket("192.168.0.100", 13267);
System.out.println("Connecting to : " + sock);

InputStream in = sock.getInputStream();
FileOutputStream out = new FileOutputStream("received.txt");

int bytes = 0;
byte[] buffer = new byte[8192];
int len;

long start = System.currentTimeMillis();

while ((len = in.read(buffer)) > 0) {
    out.write(buffer, 0, len);
    bytes += len;
}

long end = System.currentTimeMillis();

out.close();
sock.close();

double kbps = (bytes / 1000) / ((end - start) / 1000);
System.out.println("Speed: " + kbps + " kbps");

这是因为我正在使用自己的缓冲区,这会减慢所有速度,还是可能是什么问题?也欢迎提示和提示。

【问题讨论】:

    标签: java file sockets speed-test


    【解决方案1】:

    如果您想测量带宽而无需发送文件,则只需发送空白数据即可。如果文件不够大,建立连接的成本(通常为 20 毫秒)会使您的连接显得很慢。

    我建议你发送数据至少 2 到 10 秒。

    本文提供了有关通过套接字传输数据的最快方法的示例代码。 How fast are Java sockets


    使用整数运算产生浮点数很可能会出错。

    double kbps = (bytes / 1000) / ((end - start) / 1000);
    

    假设bytes 是 2100,end - start 是 1900,你会得到

    double kbps = (2100 / 1000) / (1900 / 1000);
    double kbps = 2 / 1; == 2.
    

    几乎相同(但错误更少)

    double kbps = bytes / (end - start);
    

    更好

    double kbps = (double) bytes / (end - start);
    

    发送空白数据

    byte[] bytes = new byte[8*1024];
    OutputStream out = socket.getOutputStream();
    // send data for given amount of time, e.g. 2000 ms
    long endTime = System.currentTimeMS() + timeToSendDataMS;
    do {
        out.write(bytes);
    } while(endTime > System.currentTimeMS());
    

    读取空白数据

    long total = 0;
    byte[] bytes = new byte[8*1024];
    InputStream in = socket.getInputStream();
    int len;
    while((len = in.read(bytes)) != -1)
        total += len;
    

    【讨论】:

    • 谢谢你的两个回答,你怎么能发送空白数据?
    • @Jens,我已将其添加到我的答案中。 ;)
    【解决方案2】:

    这是因为您写入磁盘您收到在客户端的每个 8K 包。

    FileOutputStream out = new FileOutputStream("received.txt");
    ...
    while ((len = in.read(buffer)) > 0) {
        out.write(buffer, 0, len);
        ...
    }
    

    这对于速度测试不是必需的。只需将字节读入缓冲区就足够了。跳过将包写入客户端代码中的文件。 或者,您可以将收到的包写入ByteArrayOutputStream。 Java 将在 JVM 的堆空间中自行处理分配。并且不会影响速度测试。

    【讨论】:

    • 谢谢,我已经删除了输出流。
    【解决方案3】:

    您的代码无效。您在错误的时间点结束计时器。在您刷新或关闭输出流之前,传输不会完成。

    【讨论】: