0

我正在尝试编写一个程序来实现距离矢量算法。所以我需要节点同时充当服务器和客户端。

基本上我使用 UDP 协议来发送和接收消息。我正在尝试收听来自相邻节点的消息,同时每 5 秒发送一次节点的距离向量。

我的主要问题是我希望停止收听消息,以便我可以广播我的距离矢量。我尝试使用setSoTimeout,但后来我得到了各种我不知道如何处理的异常。而且我不太确定如何再次“重新打开”套接字以再次等待消息或继续广播消息....

有人可以指出我正确的方向吗?

我的代码如下:

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;


public class dv_routing {

public static void main(String[] args) throws Exception {

    //initialise variables to default value
    int NodeID = 0;
    int NodePort = 6000;
    String configFile = "A.txt";
    int numNbr = 0;                                     // zero neighbour
    double[] CostList = new double[10];                 //Self cost list
    Arrays.fill(CostList, Double.POSITIVE_INFINITY);
    int[] ViaList = new int[10];                        //Self cost list
    Arrays.fill(ViaList, 9999);
    double[] Cost = new double[10];                     //Inf cost array for Nbr initialization
    Arrays.fill(Cost, Double.POSITIVE_INFINITY);        
    Neighbour Nbr = new Neighbour();                    //create Nbr
    boolean ischanged = false;


    //read user input
    if (args.length >= 3) {
        System.out.println("i'm here!");
        String tmp = args[0];
        char tmpchar = tmp.charAt(0);
        NodeID = ((int)tmpchar - 65);
        NodePort = Integer.parseInt(args[1]);
        configFile = args[2];
        CostList[NodeID] = 0;
        System.out.println(NodeID);
        System.out.println(NodePort);
        System.out.println(configFile);
        //poison reverse
        if (args.length <= 4) {
            // TODO: poison reverse
        }
        else 
            System.out.println("Incorrect Input Format! Please try again!");
    }


       //reading config file for neighbour data
    try{

          // Open the file that is the first 
          // command line parameter
          FileInputStream fstream = new FileInputStream(configFile);
          // Get the object of DataInputStream
          DataInputStream in = new DataInputStream(fstream);
          BufferedReader br = new BufferedReader(new InputStreamReader(in));
          String strLine;
          //capture the number neighbours
          if ((strLine = br.readLine()) != null){
              numNbr = Integer.parseInt(strLine);
              System.out.println (numNbr);
          }
          int elementcnt = 0;
          while ((strLine = br.readLine()) != null)   {
              //separate data 
              String[] temp = strLine.split(" ");

              //get neighbour Node ID
              char tmpchar = temp[0].trim().charAt(0);
              int ID = (int)(tmpchar - 65);
              //NbrIDList.add(new NbrID((int)tmpchar - 65));
              //get neighbour cost
              CostList[ID] = Double.parseDouble(temp[1].trim());
              ViaList[ID] = ID;
              //get neighbour port number
              int Port = Integer.parseInt(temp[2].trim());

              //create entry for neighbour
              Nbr.addData(ID, Port);
              Nbr.addCost(Cost);

              //debugging
              //System.out.println((char)(Nbr.getID(elementcnt)+65));
              //System.out.println(Nbr.getPort(elementcnt));
              //System.out.println(Nbr.getCost(elementcnt)[0]);

              elementcnt++;
          }
          //Close the input stream
          in.close();
            }catch (Exception e){//Catch exception if any
                System.err.println("Error: " + e.getMessage());
          }



    //set timers
    long now = System.currentTimeMillis();
    long end = now + 50 * 1000;
    long broadcast = now + 1 * 1000;
    long current = System.currentTimeMillis();

    while(current < end) {
        System.out.println("in first layer");

        //open UDP socket for listening..
        DatagramSocket nodeSocket = new DatagramSocket(NodePort);
        InetAddress IPAddress = InetAddress.getByName("localhost");
        byte[] receiveData = new byte[1024];
        byte[] sendData = new byte[1024];

        //braodcast...
        String OutMsg = CostList[0]+"\t"+CostList[1]+"\t"+CostList[2]+"\t"+CostList[3]+"\t"+CostList[4]+"\t"+CostList[5]+"\t"+CostList[6]+"\t"+CostList[7]+"\t"+CostList[8]+"\t"+CostList[9];
        sendData = OutMsg.getBytes();
        for (int i = 0; i < numNbr; i++){
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, Nbr.getPort(i));
            nodeSocket.send(sendPacket);
        }

        nodeSocket.setSoTimeout(1000);

        while(current < broadcast){
            if (nodeSocket.isClosed()){
                nodeSocket = new DatagramSocket(NodePort);
            }
            System.out.println("in receiving layer");
            current = System.currentTimeMillis();
            ischanged = false;
            //get MSG
            // Msg format.. "cost1"\t"cost2"\t"cost3"...
            try{DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            nodeSocket.receive(receivePacket);

            System.out.println("we got here");
            String Msg = new String( receivePacket.getData());
            System.out.println("RECEIVED: " + Msg);
            int NbrPort = receivePacket.getPort();
            System.out.println("From: " + NbrPort);

            //process the MSG
            String[] tmpstr = Msg.split("\t");
            for (int i = 0; i<10; i++) {
                Cost[i] = Double.parseDouble(tmpstr[i]);
            }
            int Idx = Nbr.indexOfPort(NbrPort);
            System.out.println("From: " + NbrPort);
            Nbr.updateCost(Idx, Cost);

            //compare cost and update list
            for (int i = 0; i<10;i++) {
                double NbrNodeCost = (Nbr.getCost(Idx)[i] + CostList[Nbr.getID(Idx)]);
                if (!(Double.isInfinite(NbrNodeCost)) && CostList[i] > NbrNodeCost) {
                    CostList[i] = NbrNodeCost;
                    ViaList[i] = Nbr.getID(Idx);
                    ischanged = true;
                }
            }

            System.out.println("Is the list changed? " + ischanged);
            System.out.println(CostList[0]+" "+CostList[1]+" "+CostList[2]+" "+CostList[3]+" "+CostList[4]+" "+CostList[5]+" "+CostList[6]+" "+CostList[7]+" "+CostList[8]+" "+CostList[9]);
            System.out.println(ViaList[0]+" "+ViaList[1]+" "+ViaList[2]+" "+ViaList[3]+" "+ViaList[4]+" "+ViaList[5]+" "+ViaList[6]+" "+ViaList[7]+" "+ViaList[8]+" "+ViaList[9]);
            }catch (SocketTimeoutException e) {
                //System.err.println("Caught SocketException: " + e.getMessage());
                System.out.println("Timeout reached!!! " + e);
                nodeSocket.close();
                nodeSocket = new DatagramSocket(NodePort);
                current = System.currentTimeMillis();

            }
            catch (SocketException e1){
                System.out.println("Socket closed " + e1);
            }

        }
        //Broadcast List
        System.out.println("broadcast");

        broadcast = current + 1 * 1000;
        current = System.currentTimeMillis();
        if (ischanged) {
            end = current + 10 * 1000;
        }
        //braodcast...
        OutMsg = CostList[0]+"\t"+CostList[1]+"\t"+CostList[2]+"\t"+CostList[3]+"\t"+CostList[4]+"\t"+CostList[5]+"\t"+CostList[6]+"\t"+CostList[7]+"\t"+CostList[8]+"\t"+CostList[9];
        sendData = OutMsg.getBytes();
        for (int i = 0; i < numNbr; i++){
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, Nbr.getPort(i));
            nodeSocket.send(sendPacket);
        }

    }

    //Print List
    //Shortest path to node B: the next hop is C and the cost is 5
    for(int i = 0; i <10; i++) {
        if(ViaList[i] != 9999){
            System.out.println("Shortest path to node "+(char)(i+65)+": the next hop is "+(char)(ViaList[i])+" and the cost is "+CostList[i]);
        }
    }

    System.out.println("end");


}


}

class Neighbour {

public Neighbour(){
    NbrIDList = new ArrayList<Integer>();
    NbrPortList = new ArrayList<Integer>();
    NbrCostList = new ArrayList<double[]>();
}

public void addData(int ID, int Port){
    NbrIDList.add(ID);
    NbrPortList.add(Port);
}

public void addCost(double[] Cost){
    NbrCostList.add(Cost);
}

public int getID(int idx){
    return (Integer) NbrIDList.get(idx);
}

public int getPort(int idx){
    return (Integer) NbrPortList.get(idx);
}

public int indexOfPort(int Port){
    return (Integer) NbrPortList.indexOf(Port);
}

public double[] getCost(int idx){
    return (double[]) NbrCostList.get(idx);
}

public void updateCost(int idx, double[] Cost){
    NbrCostList.set(idx,Cost);
}

private ArrayList<Integer> NbrIDList;
private ArrayList<Integer> NbrPortList;
private ArrayList<double[]> NbrCostList;

}
4

1 回答 1

2

网络几乎是 99.8% 的线程。为了解决您的问题,您可以创建一个线程来接收消息,并创建第二个线程用于每 5 秒发送消息。

对此有很多疑问:

Java:多线程和 UDP 套接字编程

如何在 Java 中实现基于线程的 UDP 服务器?

java2s也不错:

服务器

客户

于 2012-10-12T14:22:17.320 回答