我在使用NIO框架在主机和客户端之间通过SocketChannel发送数据时遇到了问题。NIO挂起问题?
我从来没有真正困扰过之前学习NIO,但随着java.nio.files包和其他各种改进的介绍,我想我会试试看。
我能够得到SocketChannel和ServerSocketChannel连接正常,但实际的数据传输行为非常奇怪。它永远不会在客户端正确完成,在最终读取后总是挂起。此外,它有时会读取不正确数量的数据(太多或太少),甚至导致Windows资源管理器发疯,从字面上分配系统的所有内存,导致计算机崩溃。
下面是代码(它是测试代码)我有现在:
package bg.jdk7.io;
import static java.nio.file.StandardOpenOption.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class NetIO {
static volatile long filesize;
public static void main(String[] args) {
new Thread(new Client()).start();
try {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(5555));
SocketChannel sc = ssc.accept();
if(sc.isConnected()) {
ByteBuffer buff = ByteBuffer.allocate(10240);
Path fp = Paths.get(System.getProperty("user.home")+"\\Documents\\clip0025.avi");
if(Files.exists(fp)) {
FileChannel fc = (FileChannel) Files.newByteChannel(fp, StandardOpenOption.READ);
long tot = Files.size(fp);
long run = 0;
int read = 0;
int prog = 0;
while((read = fc.read(buff))>0) {
buff.rewind();
sc.write(buff);
run+=buff.position();
int last = prog;
prog = (int)(((double)run/tot)*100);
if(prog !=last) {
System.out.println(prog + "%");
}
buff.flip();
}
fc.close();
System.out.println("Sending completed");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
static class Client implements Runnable {
public void run() {
try {
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("localhost",5555));
if(sc.isConnected()) {
Path dpf = Paths.get("\\NIO_TESTING\\");
Path dp = Paths.get(dpf+"\\clip.avi");
Files.createDirectories(dpf);
FileChannel fc = (FileChannel) Files.newByteChannel(dp, CREATE, WRITE, TRUNCATE_EXISTING);
ByteBuffer buff = ByteBuffer.allocate(10240);
int read;
int total = 0;
while((read = sc.read(buff))>0) {
total+=read;
buff.rewind();
fc.write(buff);
System.out.println(fc.size());
buff.flip();
if(total == filesize) System.out.println("File data received successfully...");
}
System.out.println("Completed successfully");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
呃...是的,我是NIO以及JDK 7 API的新手。尽管感谢您的帮助。我会尝试这些改变。怎么样buffer.rewind()?这是否需要使用? – bgroenks
并且不会关闭SocketChannel关闭底层套接字? – bgroenks
@ ghostsoldier23这不是JDK 7 API。大部分是JDK * 1.4 * API。正如它在Javadoc中所说,关闭通道当然关闭了插座,但是你没有这样做。你关闭的唯一的东西是FileChannel,并且只在服务器中。所以你缺少三个关闭。你不需要'buffer.rewind()',就是我发布的内容。 – EJP