У меня возникли проблемы с отправкой данных через SocketChannels между хостом и клиентом с использованием инфраструктуры NIO.Проблемы с NIO Hang Up?
Я до сих пор не потрудился изучить NIO, но с введением пакета java.nio.files и других улучшений я думал, что попробую.
Я могу получить SocketChannel и ServerSocketChannel для подключения нормально, но фактическая передача данных действует очень странно. Он НИКОГДА не заканчивается правильно на стороне клиента, всегда зависает после окончательного чтения. Кроме того, он иногда считывает неверный объем данных (слишком много или слишком мало), и даже заставил Windows Explorer сходить с ума и выделить буквально ВСЕ память системы, сбой компьютера.
Вот код (это тестовый код) я прямо сейчас:
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();
}
}
}
Er ... да Я новичок в NIO, а также в JDK 7 API. Спасибо за вашу помощь. Я попробую эти изменения. Что относительно buffer.rewind()? Нужно ли это использовать? – bgroenks
И не закрывал ли SocketChannel закрытие базового Socket? – bgroenks
@ ghostsoldier23 Это не API JDK 7. Большая часть из них - API JDK * 1.4 *. Конечно, закрытие канала закрывает сокет, как говорится в Javadoc, но вы этого не делаете. Единственное, что вы закрываете, это FileChannel, и это только на сервере. Таким образом, вам не хватает трех закрытий. Вам не нужен 'buffer.rewind()', только то, что я разместил. – EJP