答复: (fc) FileChannel.transferFrom/transferFromArbitraryChannel to return -1 at some error condition
lihuaming (A)
lihuaming3 at huawei.com
Fri Jan 29 12:51:32 UTC 2021
(Sorry for the format, I had some trouble to configure thunderbird in my environment)
Hi Hamlin,
The transferFrom method returns the number of bytes written to the file. Changing the spec to allow it return -1 would be an incompatible change and could potentially break usages that keep a running total of bytes transferred.
Hi Alan,
Yes, I think so too. But still like to see if we can improve it a little bit.
Can you expand a bit on the scenario? If the underlying connection has been reset or there is another error then I would expect the read from the source channel to fail (SocketException "connection reset" for example). This is different to the peer closing the connection gracefully where reading from the source channel returns -1/EOF and there are no bytes written to the file.
Here is a simple demo, I don't use FileChannel.transferFrom directly, but I hope I can clarify the situation.
When ServerHangHttp and Client are up for a while (please check the bottom), no matter Server close the socket explicitly or kill by "kill -9 xxx", the client side will print out "[client] read : -1" continuously. so, if we are using FileChannel.transferFrom which will call transferFromArbitraryChannel which will call ReadableByteChannel.read, ReadableByteChannel.read will return -1, but transferFromArbitraryChannel will return 0, so as FileChannel.transferFrom. Based on this return value, following while loop will be a infinite loop, and user don't want to call something like "call sth like srcSocketChannel.read(...)", please check the reason in comments below.
while (srcSocketChannel.isOpen()) {
long l = fileChannel.transferFrom(srcSocketChannel,...);
// user could call sth like srcSocketChannel.read(...), and expect it return -1, and break the loop, but it will be unacceptable for some program, where they would like to very quick copy, so called "zero" copy through fileChannel.transferFrom, and they don't want to add an extra check like "srcSocketChannel.read(...)"
if (l == -1) { // break out the while loop }
}
At this situation, I think it's more friendly to have fileChannel.transferFrom returns -1.
Thanks,
Hamlin
=========== ServerHangHttp and Client ==============
public class ServerHangHttp {
public static void main(String args[]) throws Exception {
ServerSocketChannel server = ServerSocketChannel.open();
server.bind(new InetSocketAddress("127.0.0.1", 9876));
System.out.println(" waiting for client...");
SocketChannel client = server.accept();
System.out.println(" get client connection successfully");
System.out.println(" socket: " + client);
int i = 0;
while (client.isOpen()) {
System.out.println(" write some bytes to client");
client.write(ByteBuffer.wrap("abc".getBytes()));
Thread.sleep(1000);
/*
* if (++i == 10) {
System.out.println(" socket is closed");
client.close();
break;
}*/
}
}
}
public class Client {
public static void main(String args[]) throws Exception {
SocketChannel client = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9876));
System.out.println("[client] socket: " + client);
int i = 0;
ByteBuffer buf = ByteBuffer.allocate(1000);
while (true) {
int x = client.read(buf);
System.out.println("[client] read : " + x);
Thread.sleep(1000);
}
}
}
-Alan.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/nio-dev/attachments/20210129/221df8ea/attachment.htm>
More information about the nio-dev
mailing list