gpt4 book ai didi

java - 通过 Java NIO API 传输文件

转载 作者:行者123 更新时间:2023-12-01 10:30:24 25 4
gpt4 key购买 nike

我正在尝试使用 Java NIO API 将 mp3 文件从服务器传输到客户端。

特别是,我尝试使用transferTo 和transferFrom 方法。

我已经检查过服务器是否正确识别该文件并将其传输到 FileChannel。

但是,从客户端的角度来看,它认为与服务器连接的FileChannel的大小为0,可以解释为客户端没有从该 channel 接收到任何文件。

这是服务器和客户端控制台上的结果。

[服务器]

Server is started...

java.nio.channels.SocketChannel[connected local=/127.0.0.1:7777 remote=/127.0.0.1:60430]Here comes a new client!

!!write activated!!

Channel size : 3622994
filename : C:\Users\InhoKim\Music\5 O'clock - Black Nut.mp3
java.nio.channels.SocketChannel[connected local=/127.0.0.1:7777 remote=/127.0.0.1:60430]The number of files transferred : 1

[客户端]

!!read activated!!
Channel size : 0

我该如何解决这个问题?

这里是服务器端和客户端的完整代码

[服务器]

import java.io.File;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.net.ServerSocket;
import java.net.InetSocketAddress;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.FileChannel;
import java.io.FileInputStream;
import java.util.Set;
import java.nio.ByteBuffer;

public class MusicServer {
private Selector selector = null;
private ServerSocketChannel serverSocketChannel = null;
private ServerSocket serverSocket = null;
File dir = new File("C:\\Users\\InhoKim\\Music\\");
boolean test = true;

public static void main(String[] args) {
MusicServer ms = new MusicServer();
ms.initServer();
ms.startServer();
}

public void initServer() {
try {

selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocket = serverSocketChannel.socket();
InetSocketAddress isa = new InetSocketAddress("localhost", 7777);
serverSocket.bind(isa);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

} catch(Exception e) {e.printStackTrace();}

}

public void startServer() {

System.out.println("Server is started...");

try {
while (true) {
selector.select();

Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {

SelectableChannel channel = key.channel();

if (channel instanceof ServerSocketChannel) {
if (key.isAcceptable())
accept(key);
} else {
if (key.isWritable()) {
if(test)
write(key);
}

}
}
}
} catch(Exception e) {e.printStackTrace();}

}

private void accept(SelectionKey key) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();

try {
SocketChannel sc = server.accept();
if (sc == null) return;
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_WRITE);
System.out.println(sc.toString() + "Here comes a new client!");

} catch(Exception e) {e.printStackTrace();}

}
private void write(SelectionKey key) {
if(test)
System.out.println("!!write activated!!");
test = false;

SocketChannel sc = (SocketChannel) key.channel();
try {

File[] files = dir.listFiles();

int count = 0;
for (File file : files) {
count++;
FileInputStream fis = new FileInputStream(file);
FileChannel inChannel = fis.getChannel();
System.out.println("Channel size : " + (int)inChannel.size());
System.out.println("filename : " + file);

inChannel.transferTo(0, (int)inChannel.size(), sc);

fis.close();
break;
}
System.out.println(sc.toString() + "The number of files transferred : " + count);

} catch(Exception e) {e.printStackTrace();}
}
}

[客户端]

import java.io.File;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.SelectionKey;
import java.net.InetSocketAddress;
import java.nio.channels.FileChannel;
import java.util.Set;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;

public class MusicClient {
private Selector selector = null;
private SocketChannel sc = null;
int count = 0;

public static void main(String[] args) {
MusicClient mc = new MusicClient();
mc.startServer();
}

public void initServer() {

try {
selector = Selector.open();
sc = SocketChannel.open(new InetSocketAddress("127.0.0.1", 7777));
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);

} catch(Exception e) {e.printStackTrace();}
}

public void startServer() {
initServer();
startReader();
}

public void startReader() {
try {
while (true) {
selector.select();

Set<SelectionKey> keys = selector.selectedKeys();

for (SelectionKey key : keys) {
if (key.isReadable()) {
read(key);
System.exit(0);

}
}
}

} catch(Exception e) {e.printStackTrace();}
}

private void read(SelectionKey key) {
System.out.println("!!read activated!!");
SocketChannel sc = (SocketChannel) key.channel();
try {

File dir = new File("D:\\Target2\\");
FileOutputStream fos = new FileOutputStream(dir + "\\" + count + ".mp3"); // file name has been set as a number
count++;
FileChannel outChannel = fos.getChannel();
System.out.println("Channel size : " + (int)outChannel.size());
outChannel.transferFrom(sc, 0, (int)outChannel.size());
fos.close();

} catch(Exception e) {e.printStackTrace();}
}
}

最佳答案

in the point of view of the client, it considers that the size of the FileChannel connected to the server is 0

不存在“连接到服务器的FileChannel”这样的东西。文件 channel 连接到文件。您所拥有的是一个连接到新文件输出流的FileChannel,该文件刚刚创建了一个新文件,因此其大小为零。

which can be interpreted that the client did not receive any files from the channel.

不,它可以被解释为您告诉 FileChannel 传输零字节,它做得正确。

您无法获取 SocketChannel 的大小,因为它没有任何意义(考虑一个仅持续发送且从不关闭连接的对等点)。因此,在这种情况下,您必须使用 Long.MAX_VALUE 作为大小。当没有更多的字节要传输时,或者实际上之前,传输将完成,特别是当您使用非阻塞模式时。

编辑 我认为没有任何理由在客户端中使用非阻塞模式。我将删除它,并且 Selector.transferFrom() 必须在循环中调用,该循环在返回零时终止。如果您必须在服务器中使用非阻塞模式,则在服务器中使用 transferTo() 会复杂得多,因为您必须在返回零时注册 OP_WRITE 并重新选择和当您获得它时,使用调整后的偏移量重新启动,如果它不返回零,则取消注册OP_WRITE

关于java - 通过 Java NIO API 传输文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35122153/

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