我在使用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