gpt4 book ai didi

java - 使用 java NIO 选择器发送文件

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

我尝试使用 java NIO 选择器键从服务器发送文件,但是当我关闭服务器时,我从客户端收到整个文件。

服务器端代码

    public static int DEFAULT_PORT = 1234;

public static void main(String[] args) {
String fileName = "10mb.txt";
int port;

try {
port = Integer.parseInt(args[0]);
} catch (Exception ex) {
port = DEFAULT_PORT;
}
System.out.println("Listening for connections on port " + port);

ServerSocketChannel serverChannel;
Selector selector;
try {
serverChannel = ServerSocketChannel.open();
ServerSocket ss = serverChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
ss.bind(address);
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException ex) {
ex.printStackTrace();
return;
}

while (true) {

try {
selector.select();
} catch (IOException ex) {
ex.printStackTrace();
break;
}

Set readyKeys = selector.selectedKeys();
Iterator iterator = readyKeys.iterator();
while (iterator.hasNext()) {

SelectionKey key = (SelectionKey) iterator.next();

try {

if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
SelectionKey key2 = client.register(selector, SelectionKey.OP_WRITE);

String filePath = (fileName);
File file = new File(filePath);
int fileSize = (int) file.length();
System.out.println("File size =" + fileSize);
FileInputStream fis;
ByteBuffer buffer = null;

try {
fis = new FileInputStream(file);
FileChannel fc = fis.getChannel();
buffer = ByteBuffer.allocate(fileSize);
try {
fc.read(buffer);
} catch (IOException ex) {
System.out.println("IO EX :" + ex);
}
} catch (FileNotFoundException ex) {
System.out.println("FileNotFoundEx :" + ex);
}

buffer.flip();
key2.attach(buffer);

} else if (key.isWritable()) {

SocketChannel client = (SocketChannel) key.channel();
ByteBuffer out = (ByteBuffer) key.attachment();

client.write(out);
}

} catch (IOException ex) {
System.out.println("IO Exeption :" + ex);
key.cancel();
try {
key.channel().close();
} catch (IOException cex) {
System.out.println(cex);
}
}
iterator.remove();

}

}

}

客户端代码

public static void main(String[] args) throws IOException {
String fileName = "10mb.txt";
int bufferSize = 2048;
int n = 0;
int read = 0;

SocketChannel socket = SocketChannel.open(new InetSocketAddress(1234));
String filePath = (fileName);

FileOutputStream out = new FileOutputStream(filePath);
FileChannel file = out.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(bufferSize);

long startTime = System.currentTimeMillis();


while ((read = socket.read(buffer)) > 0) {
buffer.flip();

file.write(buffer);

n = n + read;

buffer.clear();

System.out.println(n);
}
long endTime = System.currentTimeMillis();
long difference = endTime - startTime;
System.out.println("File with " + n + " bytes downloaded in " + difference + " ms");
socket.close();

file.close();

out.close();
}

感谢您的帮助。

最佳答案

您假设 fc.read() 填充缓冲区,而 sc.write() 清空缓冲区。这两种假设都无效。 Java中 channel 间复制的正确方法如下:

while (in.read(buffer) > 0 || buffer.position() > 0)
{
buffer.flip();
out.write(buffer);
buffer.compact();
}

当您在非阻塞模式下输出到 SocketChannel 时,您需要针对 write() 返回零的情况进行修改:如果发生这种情况,您需要为 OP_WRITE 注册 channel ,返回到 select() 循环,并在 OP_WRITE 触发时恢复此循环:这一次,如果 write() 返回非零,取消注册 OP_WRITE

关于java - 使用 java NIO 选择器发送文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27347596/

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