4

私は現在Javaの宿題に取り組んでいます。基本的な DNS サーバーを作成するように求められました。ポート 53 でリッスンするスレッドである UDPSender クラスがあります。UDPManager と呼ばれる別のスレッドもあります。

UDPManager は、DatagramPacket の ArrayList を保持するネストされた実行可能なクラスでスレッドを開始します。UDPSender は UDPManager を集約し、UDP パケットを受信するたびにそれをマネージャーに送信して、彼がそれを arrayList に追加できるようにします。

import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.HashMap;


public class UDPManager {
private UDPManagerRunnable manager;

public UDPManager(String hostsFile, String remoteDNS, boolean localResolution) {
    manager = new UDPManagerRunnable(hostsFile, remoteDNS, localResolution);
    new Thread(manager).start();
}

public void managePacket(DatagramPacket p) {
    manager.managePacket(p);
}

public void close() {
    manager.close();
}

private class UDPManagerRunnable implements Runnable {
    private ArrayList<DatagramPacket> packets;
    private HashMap<Integer, String> clients;
    private boolean localResolution;
    private boolean running;
    private String hostsFile;
    private String remoteDNS;

    public UDPManagerRunnable(String hostsFile, String remoteDNS, boolean localResolution) {
        packets = new ArrayList<DatagramPacket>();
        clients = new HashMap<Integer, String>();
        this.localResolution = localResolution;
        this.running = true;
        this.hostsFile = hostsFile;
        this.remoteDNS = remoteDNS;
    }

    public void managePacket(DatagramPacket p) {
        packets.add(p);
        System.out.println("Received packet. "+packets.size());
    }

    public void close() {
        running = false;
    }

    public void run() {
        DatagramPacket currentPacket = null;
        while(running) {
            if(!packets.isEmpty()) {
                currentPacket = packets.remove(0);
                byte[] data = currentPacket.getData();
                int anCountValue = data[Constant.ANCOUNT_BYTE_INDEX];
                if(anCountValue == Constant.ANCOUNT_REQUEST)
                    this.processRequest(currentPacket);
                else if(anCountValue == Constant.ANCOUNT_ONE_ANSWER)
                    this.processResponse(currentPacket);

            }
        }

    }

    private void processRequest(DatagramPacket packet) {
        System.out.println("it's a request!");
    }

    private void processResponse(DatagramPacket packet) {
        System.out.println("it's a response!");
    }

}

}

これが UDP マネージャーです。System.out.println が「Received packet」を正しく表示するので、パケットはマネージャに正しく送信されます。配列のサイズは増加します。私が直面している問題は、「ru​​n()」内でサイズが大きくならないことです。奇妙なことは、デバッグで完全に正常に動作することです。なぜこのように振る舞うのか分かりますか?

どうもありがとうございました。

4

2 に答える 2

0

アクセスまたは変更するときは、パケットを同期する必要があります

于 2012-11-24T01:18:18.100 に答える
0

問題は、最初のスレッドが新しいデータをパケット変数に入れているが、2 番目のスレッドではこれが見えないことです。アレイへのアクセスを同期する必要があります。

2 番目のスレッドを開始すると、すべての変数がコピーされます。2 番目のスレッドは、コピーに対してのみ機能します。この変数へのアクセスを同期する必要があるため、変更が他のスレッドから見えるようになります。

于 2012-11-19T15:53:05.857 に答える