Я начинаю программировать Java NIO и создаю две отдельные программы Java. Один из них - создать некоторые случайные данные для отправки по протоколу UDP, а другой - для получения этих данных и, возможно, выполнить некоторую обработку на нем.Java DatagramChannel зависает
В каждом классе я определил РАЗМЕР данных, которые должны быть отправлены/приняты, и количество байтов, отправляемых или получаемых за один раз (за пакет) с 8 байтами. Когда у меня есть РАЗМЕР 1024 байта, я могу включить приемник (который по умолчанию ждет некоторых пакетов, чтобы прибыть), после чего я включаю отправителя, который отправляет пакеты, и получатель правильно принимает эти пакеты и завершает работу, когда все пакеты принимаются. Затем я попытался установить SIZE в 10 мегабайт. Я запускаю приемник, а затем запускаю отправителя. Отправитель, кажется, работает нормально и заканчивается через несколько секунд. Приемник начинает работать и переходит к чтению нескольких пакетов (я поставил несколько строк вокруг кода). Однако, где-то в процессе, приемник, кажется, виснет и перестает получать больше пакетов. Я не знаю, где происходит зависание, за исключением того, что это происходит сразу после очистки буфера для нового чтения.
Возможно, я неправильно использую библиотеку. Буду признателен за любую оказанную помощь.
Класс отправителя называется UDPSender, как показано ниже:
public class UDPSender {
public static void main(String[] args) {
try {
// Generate some data to send
int SIZE=1024*1024*10;
int bufferBytes = 8;
byte[] b = new byte[SIZE];
new Random().nextBytes(b);
String value = new String(b);
//System.out.println(value);
// Create Datagram channel for sending UDP packets
DatagramChannel sendingChannel = DatagramChannel.open();
// Bind the channel to a specific sending socket address and port
InetSocketAddress sendSocket = new InetSocketAddress("127.0.0.1", 9999);
sendingChannel.socket().bind(sendSocket);
//Target socket address
InetSocketAddress targetSocket = new InetSocketAddress("127.0.0.1", 8888);
//loop to send bufferBytes bytes at a time
int location = 0;
int bytesSent = 0;
long startTime=0; long endTime=0; long elapsedTime=0; // for speed benchmarking
startTime = System.nanoTime();
for (int i = 1; i <= SIZE/bufferBytes; i++) {
//System.out.println(i);
ByteBuffer buf = ByteBuffer.allocate(bufferBytes);
buf.clear();
buf.put(Arrays.copyOfRange(b, location, location + bufferBytes));
location = location + bufferBytes;
buf.flip();
bytesSent = bytesSent + sendingChannel.send(buf, targetSocket);
}
endTime = System.nanoTime();
elapsedTime = endTime - startTime;
double elapsedTimeMs = elapsedTime/1000000.0;
System.out.println("Elapsed:" + elapsedTimeMs + " msec");
} catch (IOException ex) {
Logger.getLogger(UDPSender.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Второй класс называется UDPReceiver, как показано ниже:
public class UDPReceiver {
public static void main(String[] args) {
try {
int SIZE=1024*1024*10;
int bufferBytes = 8;
int packet_max = SIZE/bufferBytes;
// Create Datagram channel for receiving UDP packets
DatagramChannel receivingChannel = DatagramChannel.open();
// Bind the channel to a specific receiving socket address and port
InetSocketAddress receiveSocket = new InetSocketAddress("127.0.0.1",8888);
receivingChannel.socket().bind(receiveSocket);
// Set up address of send
InetSocketAddress sendSocket = new InetSocketAddress("127.0.0.1",9999);
// Connect our receiving socket to their sending socket address
receivingChannel.connect(sendSocket);
long startTime=0; long endTime=0; long elapsedTime=0; // for speed benchmarking
byte[] b = new byte[SIZE]; //receiving storage
int packets=0; int location=0; int bytesCount; //byte[] indexes
boolean clockStart=false;
//try indirect ByteBuffer
System.out.println("Indirect ByteBuffer()");
ByteBuffer buf = ByteBuffer.allocate(bufferBytes);
packets=0; location=0; bytesCount = 0; clockStart=false;
while ((bytesCount = receivingChannel.read(buf)) > 0) { // Read data from file into ByteBuffer
System.out.println(".");
if(clockStart==false){
startTime = System.nanoTime();
clockStart=true;
}
// flip the buffer which set the limit to current position, and position to 0.
buf.flip(); System.out.println("..");
System.arraycopy(buf.array(), 0, b, location, buf.capacity()); System.out.println("..."); // Write data from ByteBuffer to bytearray
location=location+bufferBytes; System.out.println("....");
buf.clear(); System.out.println("....."); // For the next read
packets = packets+1; System.out.println("......");
if(packets==packet_max){
System.out.println(".......");
System.out.println(packets);
break;
}
}
endTime = System.nanoTime();
elapsedTime = endTime - startTime;
System.out.println("ByteBuffer() Elapsed Time is " + (elapsedTime/1000000.0) + " msec");
} catch (IOException ex) {
System.out.println(ex.toString());
//Logger.getLogger(UDPReceiver.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Почему 8 байтов? Восемь байтов полезной нагрузки и 28 байтов служебных данных заголовка UDP не имеют большого смысла. – EJP
Привет @EJP - Спасибо за чтение. У меня нет особых причин для 8 байтов. Это просто пример, с помощью которого я пытаюсь узнать о UDP, NIO и т. Д. Такая же проблема возникает даже при больших нагрузках, например. 64 байта. –
Некоторые дополнительные подробности после отладки: я замедлял скорость UDPSender, вставив Thread.sleep (1); после каждого отправленного пакета, и теперь получатель может пройти весь цикл. Кажется, это ограничение на пакет UDP-пакетов, которые могут быть приняты за один раз. –