gpt4 book ai didi

java - 通过 SocketChannel 传输文件时丢失字节

转载 作者:行者123 更新时间:2023-12-01 06:16:03 24 4
gpt4 key购买 nike

我正在使用 nio ServerSocketChannel 和 SocketChannel 在客户端和服务器之间传输大文件。问题是当我将大小为 6060064 字节的文件从发送方传输到接收方时,接收方仅收到 6059040 字节,缺少一些字节。由于文件大小变得更大,丢失字节的差异差距增加。我找不到为什么这些字节丢失。

发件人代码:

public boolean send(SelectionKey selectionKey) {

File file = new File("/media/data1/sample.mp4");
try {
SocketChannel socketChannel = (SocketChannel) selectionKey
.channel();
FileInputStream fileInputStream = new FileInputStream(file);
System.out.println("File Length :: " + file.length());
System.out.println("File lastModified :: " + file.lastModified());

FileChannel fileChannel = fileInputStream.getChannel();

transfer(fileChannel, socketChannel, file.length(), 1024 * 50);

fileInputStream.close();

System.out.println("File Send Completely Done 100%....");
System.out.println("Closing Connection 100%....");

return true;

} catch (Exception e) {
System.out.println(e);
System.out.println("Connection Failed. Connectiontimeout.");
return false;
}
}

public static void transfer(FileChannel fileChannel,
SocketChannel socketChannel, long lengthInBytes,
long chunckSizeInBytes)
throws IOException {

long overallBytesTransfered = 0L;
long time = -System.currentTimeMillis();

while (overallBytesTransfered < lengthInBytes) {

long bytesTransfered = 0L;

bytesTransfered = fileChannel.transferTo(
overallBytesTransfered,
Math.min(chunckSizeInBytes, lengthInBytes
- overallBytesTransfered), socketChannel);

System.out.println("bytesTransfered :: " + bytesTransfered);

overallBytesTransfered += bytesTransfered;

System.out.printf(
"overall bytes transfered: %s progress %s%%\n",
overallBytesTransfered, Math.round(overallBytesTransfered / ((double) lengthInBytes) * 100.0));
}

time += System.currentTimeMillis();

System.out.printf("Transfered: %s bytes in: %s s -> %s kbytes/s\n",
overallBytesTransfered, time / 1000,
(overallBytesTransfered / 1024.0) / (time / 1000.0));
System.out.println("------- File transfer completed ------");

}

接收者代码:

public boolean recieve(SelectionKey key) {
SocketChannel socketChannel = null;
Socket socket = null;

try {
socketChannel = (SocketChannel) key.channel();
socket = socketChannel.socket();
System.out.println(socketChannel.getRemoteAddress());

// Save file destination
String FileKey = "/media/data1/Test/sample1.mp4";
// File size
long sizeInBytes = 6060064;

long timeStap = 1402301850000l;

File file = new File(FileKey);
FileOutputStream fileOutputStream = new FileOutputStream(file);
FileChannel fileChannel = fileOutputStream.getChannel();

transfer(fileChannel, socketChannel, sizeInBytes, 1024 * 100);

fileOutputStream.close();

file.setLastModified(timeStap);
socket.close();
return true;

} catch (Exception e) {
System.out.println("Connection Failed. Connectiontimeout.");
e.printStackTrace();
return false;
}
}

public static void transfer(FileChannel fileChannel,
SocketChannel socketChannel, long lengthInBytes, long chunckSizeInBytes)
throws IOException {

long overallBytesTransfered = 0L;
long time = -System.currentTimeMillis();
while (overallBytesTransfered < lengthInBytes) {

long bytesTransfered = 0L;

bytesTransfered = fileChannel.transferFrom(
socketChannel,
overallBytesTransfered,
Math.min(chunckSizeInBytes, lengthInBytes
- overallBytesTransfered));

System.out.println("bytesTransfered :: " + bytesTransfered);

overallBytesTransfered += bytesTransfered;

System.out.printf(
"overall bytes transfered: %s progress %s%%\n", overallBytesTransfered,
Math.round(overallBytesTransfered / ((double) lengthInBytes) * 100.0));

}

time += System.currentTimeMillis();

System.out.printf("Transfered: %s bytes in: %s s -> %s kbytes/s\n",
overallBytesTransfered, time / 1000,
(overallBytesTransfered / 1024.0) / (time / 1000.0));
System.out.println("-------Dateiübertragung fertig------");

}

发送者的输出:

bytesTransfered :: 18464

overall bytes transfered: 6060064 progress 100%

Transfered: 6060064 bytes in: 119 s -> 49.67708595651809 kbytes/s

接收器输出:

bytesTransfered :: 0

overall bytes transfered: 6059040 progress 100%

接收器的 while 循环一直持续到我手动停止该进程,并且 bytesTransfered 在接收器端始终返回零,而文件大小增加到 6059040 字节。

请谁能告诉我为什么这些字节丢失了。

最佳答案

我们在 JDK7u60 上看到了同样的情况(我们之前没有看到)

我们注意到,如果缓冲区大于约 200KB,则 SocketChannel 在接收方有时间读取套接字之前关闭。

到目前为止,我们唯一的建议是通过暂停来限制写入

int bytes = socketChannel.write(currentWriteBuffer);
if (bytes > 200000) {
try {
Thread.sleep(100 * (bytes / 200000));
}
catch (InterruptedException e) {
// ignore
}
}

我还没有研究实际的限制或实际的延迟,但这对我们有用。请注意,我在研究更好的答案时发现了您的问题。

关于java - 通过 SocketChannel 传输文件时丢失字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24547153/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com