如何模拟ad hoc网络节点?

时间:2017-12-28 14:51:29

标签: java multithreading networking

我有类Source,Intermediate和Destination。源类有一些概率接收新数据包发送的方法。无论何时收到数据包,都应将其广播(通过某种setPacket方法模拟)到所有邻居中间节点。中间节点应将这些数据包广播到其邻居,直到数据包到达目的地。问题是无论何时启动数据包传输链,源节点都会停止运行其获取新数据包的方法。因此,基本上源类被冻结而函数链正在工作。有没有办法同时运行这两个进程? (就像Source节点会向Intermediate类发送请求,并且那个人会独立完成它的工作)我尝试了三个类中的每一个来扩展Thread类但是传输链仍然是冻结Source类。使用的语言是Java,但如果还有其他语言可以完成这项工作,我可以切换到它们。

public class Main {
    public static void main(String[] args) {
        // init nodes
        SourceNode sourceNode = new SourceNode();
        IntermediateNode intermediateNode1 = new IntermediateNode();
        IntermediateNode intermediateNode2 = new IntermediateNode();
        IntermediateNode intermediateNode3 = new IntermediateNode();
        DestinationNode destinationNode = new DestinationNode();

        // create network topology, S - I - I - I - D
        sourceNode.setNextNode(intermediateNode1);
        intermediateNode1.setNextNode(intermediateNode2);
        intermediateNode2.setNextNode(intermediateNode3);
        intermediateNode3.setNextNode(destinationNode);

        // setup listeners
        sourceNode.setSetupMessageListener(intermediateNode1);
        intermediateNode1.setSetupMessageListener(intermediateNode2);
        intermediateNode2.setSetupMessageListener(intermediateNode3);
        intermediateNode3.setSetupMessageListener(destinationNode);

        sourceNode.run();
    }
}

public interface SetupMessageListener {
    void onNewSetupMessage();
}

public class Node {
    protected SetupMessageListener setupMessageListener;
    protected Node nextNode;
    public void setNextNode(Node nextNode) {
        this.nextNode = nextNode;
    }
    public void setSetupMessageListener(SetupMessageListener setupMessageListener) {
        this.setupMessageListener = setupMessageListener;
    }
}

import java.util.Random;

public class SourceNode extends Node implements Runnable {
    @Override
    public void run() {
        while(true) {
            // simulate generating new setup message with probability 1/10
            Random random = new Random();
            int rv = random.nextInt(10);
            if (rv == 0) {
                createNewSetupMessage();
            }
        }
    }
    public void createNewSetupMessage() {
        System.out.println("New setup message was created in Source Node");
        if (setupMessageListener != null) {
            setupMessageListener.onNewSetupMessage();
        }
    }
}

public class IntermediateNode extends Node implements SetupMessageListener {
    public static int count = 0;
    private int id;
    public IntermediateNode() {
        id = count++;
    }
    @Override
    public void onNewSetupMessage() {
        System.out.println("Intermediate Node " + id + " got notified about setup message");
        // pass setup message to next neighbor
        setupMessageListener.onNewSetupMessage();
    }
}

public class DestinationNode extends Node implements SetupMessageListener {
    @Override
    public void onNewSetupMessage() {
        System.out.println("Destination Node got notified about new setup message");
    }
}

示例输出

New setup message was created in Source Node
Intermediate Node 0 got notified about setup message
Intermediate Node 1 got notified about setup message
Intermediate Node 2 got notified about setup message
Destination Node got notified about new setup message
New setup message was created in Source Node
Intermediate Node 0 got notified about setup message

然而,我希望它像是

New setup message was created in Source Node
Intermediate Node 0 got notified about setup message
New setup message was created in Source Node
Intermediate Node 1 got notified about setup message
Intermediate Node 0 got notified about setup message
Intermediate Node 2 got notified about setup message
Destination Node got notified about new setup message

1 个答案:

答案 0 :(得分:1)

问题是整个消息传递是在主线程中完成的......你需要实现createNewSetupMessageonNewMessageSetup的功能作为Runnable的实例并启动新的线程来运行它们。

public class SetupMessageSender implements Runnable{


    private SetupMessageListener setupMessageListener;

    public SetupMessageSender(SetupMessageListener setupMessageListener){
        this.setupMessageListener = setupMessageListener;
    }

    @Override
    public void run() {
        if (setupMessageListener != null) {
            setupMessageListener.onNewSetupMessage();
        }
    }

    public SetupMessageListener getSetupMessageListener() {
        return this.setupMessageListener;
    }

    public void setSetupMessageListener(SetupMessageListener setupMessageListener) {
        this.setupMessageListener = setupMessageListener;
    }
}

然后

    public void createNewSetupMessage() {
                System.out.println("New setup message was created in Source Node");
                Thread smService = new Thread(new SetupMessageSender(this.setupMessageListener));
                smService.start();
            }

在节点侦听器onNewMessageSetup时要小心,因为根据拓扑结构需要一些syncronization(例如,如果一个中间节点是多个不同节点的监听器),那么就这样做吧

@Override
    public synchronized void onNewSetupMessage() {
        System.out.println("Intermediate Node " + id + " got notified about setup message");
        // pass setup message to next neighbor
        Thread smService = new Thread(new SetupMessageSender(this.setupMessageListener));
        smService.start();
    }

尽管这两种方法提供了相同的功能,您可以在基类Node中将它们作为单个方法实现。