如何使用Java处理数据包?

时间:2019-06-19 11:21:32

标签: java performance

我想通过Java通过Socket发送数据包。但是我应该如何处理它以获得最佳性能和最小的故障风险?

我已经尝试过分离线程。一个正在接收,第二个正在处理分组数据。但是处理Queue的速度很快,我备份了1个线程。所以最后我认为应该有更好的方法,因为如果应用程序要长时间处理数据包,其他数据包也需要等待。

while(!isInterrupted()) {
    try {

        byte[] data = new byte[2];
        is.readFully(data);

        //GET PACKET ID
        short id = ByteBuffer.wrap(data).getShort();
        data = new byte[4];
        is.readFully(data);

        //GET PACKET SIZE
        int size = ByteBuffer.wrap(data).getInt();
        data = new byte[size];
        is.readFully(data);

        //GET DATA
        Main.getInstance().getPacketHandler().handle(id, data);
    } catch (IOException e) {
        e.printStackTrace();
        break;
    }
}           
public void handle(short id, byte[] b) {

    //GET PACKET TYPE BY ID
    PacketType type = PacketType.getById(id);

    //CREATE EVENT FROM PACKET
    Event event = type.getPacket(b).createEvent();

    //EXECUTE EVENT TO EVERY REGISTERED LISTENER TO PROCESS DATA
    for(PacketListenerInfo listener : listeners) {
        for(Method method : listener.methods) {
            if(method.getParameterTypes()[0].isInstance(event)) {
                try {
                    method.invoke(listener.listener, event);
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

就像我之前提到的,我已经尝试过这样做,但是queue列表很快就被填满了:

private Queue<HandlePacket> queue = new LinkedList<>();

public void handle(short id, byte[] b) {
    queue.add(new HandlePacket(id, b));
    synchronized (this) {
        notify();
    }
}

private class HandlePacket{
    short id;
    byte[] b;
    public HandlePacket(short id, byte[] b) {
        this.id = id;
        this.b = b;
    }
}

@Override
public void run() {
    while(!isInterrupted()) {
        if(queue == null || queue.isEmpty()) {
            try {
                synchronized (this) {
                    wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        HandlePacket hp = queue.poll();
        if(hp != null) {
            PacketType type = PacketType.getById(hp.id);
            Event event = type.getPacket(hp.b).createEvent();
            for(PacketListenerInfo listener : listeners) {
                for(Method method : listener.methods) {
                    if(method.getParameterTypes()[0].isInstance(event)) {
                        try {
                            method.invoke(listener.listener, event);
                        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

最后(对于我个人而言)最好的解决方案是:

    public void handle(short id, byte[] b) {
        data.add(new HandlePacket(id, b));
        executor.execute(new Processor(data));
    }

    class Processor implements Runnable {

        private BlockingQueue<HandlePacket> dataSource;

        public Processor(BlockingQueue<HandlePacket> dataSource) {
            this.dataSource = dataSource;
        }

        @Override
        public void run() {
            HandlePacket hp = null;
            while ((hp = dataSource.poll()) != null) {
                if(hp != null) {
                    PacketType type = PacketType.getById(hp.id);
                    if(type == null) {
                        continue;
                    }
                    Event event = type.getPacket(hp.b).createEvent();
                    for(PacketListenerInfo listener : listeners) {
                        for(Method method : listener.methods) {
                            if(method.getParameterTypes()[0].isInstance(event)) {
                                try {
                                    method.invoke(listener.listener, event);
                                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
            }
        }
    }