我有一种方法可以在while循环中监听UDP数据包。我想在它们到达时使用另一个类中的另一个方法来解析数据包,并对应用程序的另一部分中的每个数据包进行许多不同的解析和分析。我认为让PacketParser
方法处理循环外的Queue会更好。是否可以在数据包进入时将数据包添加到Queue
,然后让应用程序的另一部分在进入队列时侦听项目并执行其他操作,因为原始while循环继续侦听数据包并将它们添加到队列中?我想有另一个函数监视队列并处理数据包,Java
中有什么东西可以监视Queue
或Stack
吗?有更好的方法吗?
public void read(String multicastIpAddress, int multicastPortNumber) {
PacketParser parser = new PacketParser(logger);
InetAddress multicastAddress = null;
MulticastSocket multicastSocket = null;
final int PortNumber = multicastPortNumber;
try {
multicastAddress = InetAddress.getByName(multicastIpAddress);
multicastSocket = new MulticastSocket(PortNumber);
String hostname = InetAddress.getLocalHost().getHostName();
byte[] buffer = new byte[8192];
multicastSocket.joinGroup(multicastAddress);
System.out.println("Listening from " + hostname + " at " + multicastAddress.getHostName());
int numberOfPackets = 0;
while (true) {
numberOfPackets++;
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
multicastSocket.receive(datagramPacket);
// add to queue for another function to process the packets
}
} catch (SocketException socketException) {
System.out.println("Socket exception " + socketException);
} catch (IOException exception) {
System.out.println("Exception " + exception);
} finally {
if (multicastSocket != null) {
try {
multicastSocket.leaveGroup(multicastAddress);
multicastSocket.close();
} catch (IOException exception) {
System.out.println(exception.toString());
}
}
}
}
答案 0 :(得分:2)
好的,所以我做了一些关于生产者 - 消费者模式的阅读并想出来,所以这就是我所做的。
生产者 - 消费者模式基本上涉及三个方面:生产者,消费者和共享队列。在此上下文中,PacketReader
是接收网络数据包并将它们放入共享队列的生产者。 PacketParser
是处理共享队列中的数据包的使用者。所以我创建了一个LinkedBlockingQueue
的实例,并将该共享队列传递给了一个消费者实例(PacketReader)和一个生产者实例(PacketParser)。然后将consumer和producer实例分别传递给Thread
类的实例。最后,在每个线程实例上调用start()
方法。
public class Main {
public static void main(String[] args) {
BlockingQueue<Packet> queue = new LinkedBlockingQueue<>();
ILogger logger = Injector.getLogger();
Thread reader = new Thread(new PacketReader(logger, queue, "239.1.1.1", 49410));
Thread parser = new Thread(new PacketParser(logger, queue));
reader.start();
parser.start();
}
}
使用LinkedBlockingQueue
的原因是因为put()
方法将阻塞队列(如果已满),take()
将阻塞队列是否为空。生产者和消费者类需要实现Runnable
接口并包含一个名为run()
的方法,该方法不带参数。
消费者类
public class PacketParser implements Runnable {
private ILogger logger;
private BlockingQueue<Packet> queue;
private boolean running = true;
public PacketParser(ILogger logger, BlockingQueue<Packet> queue) {
this.logger = logger;
this.queue = queue;
}
public void stop() {
running = false;
}
public void run() {
while (running) {
Packet packet;
try {
packet = queue.take();
parse(packet);
} catch (InterruptedException exception) {
logger.Log(exception.getStackTrace().toString());
}
}
}
制作人类
public class PacketReader implements Runnable {
private ILogger logger;
private final Queue<Packet> queue;
private String multicastIpAddress;
private int multicastPortNumber;
private boolean running = true;
public PacketReader(ILogger logger, Queue<Packet> queue, String multicastIpAddress, int multicastPortNumber) {
this.logger = logger;
this.queue = queue;
this.multicastIpAddress = multicastIpAddress;
this.multicastPortNumber = multicastPortNumber;
}
public void stop() {
running = false;
}
public void run() {
InetAddress multicastAddress = null;
MulticastSocket multicastSocket = null;
try {
multicastAddress = InetAddress.getByName(multicastIpAddress);
multicastSocket = new MulticastSocket(multicastPortNumber);
String hostname = InetAddress.getLocalHost().getHostName();
byte[] buffer = new byte[8192];
multicastSocket.joinGroup(multicastAddress);
System.out.println("Listening from " + hostname + " at " + multicastAddress.getHostName());
int numberOfPackets = 0;
while (running) {
numberOfPackets++;
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
multicastSocket.receive(datagramPacket);
Packet packet = new Packet(numberOfPackets, datagramPacket);
queue.add(packet);
}
} catch (SocketException socketException) {
System.out.println("Socket exception " + socketException);
} catch (IOException exception) {
System.out.println("Exception " + exception);
} finally {
if (multicastSocket != null) {
try {
multicastSocket.leaveGroup(multicastAddress);
multicastSocket.close();
} catch (IOException exception) {
System.out.println(exception.toString());
}
}
}
}
}