1

我正在网络架构 1 中完成我的作业,我必须在每个节点上实现距离矢量路由。

在每个节点上,我都有一个线程,它DatagramPacket仅在特定端口上侦听包含来自相邻节点的路由信息​​的传入 s。当数据报到达时,线程处理该数据报,如果其内部路由表中有更新,则将其路由信息发送给所有邻居。

我正在尝试用 Java 来实现。

我面临的问题是,当数据报到达时,我需要对其进行处理。如果在此期间有任何其他数据报到达,则将其丢弃,因为线程当前正在处理信息。这意味着我丢失了信息。

谁能帮我这个?

我正在使用从 java 中的套接字读取的常用方式。

DatagramSocket socket = new DatagramSocket(4445, InetAddress.getByName("127.0.0.1"));
while (true) {
    try {
        byte[] buf = new byte[2000];

        // receive request
        DatagramPacket recvRequest = new DatagramPacket(buf, buf.length);

        socket.receive(recvRequest);

        //Some process of data in datagram

    } catch (IOException e) {
        e.printStackTrace();
    }
}
4

5 回答 5

2

您可以在一个线程中处理接收到的数据报,因此您的带有套接字侦听器的线程可以继续接收新的数据报。

于 2009-05-09T02:46:21.463 回答
1

这是我提交的最后一个项目。它可能有一些不正确的文档和 Java 的一些错误使用。由于这个项目在本地系统上运行,而不是使用不同的 IP 地址和相同的端口号,我正在做其他方式。

NetworkBoot.java 为每个路由器提供初始邻居详细信息。

谢谢-Sunny Jain

enter code here

/* * 文件名:Router.java * 公共类名:Router * */

//~--- JDK 导入 ------------------------------------------ ------------------

导入 java.io.IOException;

导入 java.net.DatagramPacket;

导入 java.net.DatagramSocket;

导入java.net.InetAddress;

导入 java.util.HashMap;

导入 java.util.Iterator;

导入 java.util.Set;

导入 java.util.concurrent.LinkedBlockingQueue;

导入 javax.swing.SwingUtilities;

/** * * NA1 项目 2009 年春季学期 * @author Sunny jain * * */

公共类路由器扩展线程{

/**
 * HashMap containing list of neighbors and cost to reach them.
 */
private HashMap<Integer, Integer> hmapDirectNeighbours = new HashMap<Integer, Integer>(61);
/**
 * HashMap containing list of destination as key and routing info to them as value.
 * Routing info contains RouteDetail object.
 * @see RouteDetail
 */
private HashMap<Integer, RouteDetail> hmapRoutes = new HashMap<Integer, RouteDetail>();
/**
 * DatagramSocket
 */
private DatagramSocket dSoc;
/**
 * DatagramPacket
 */
private DatagramPacket dpackReceive,  dpackSend;
/**
 * Inetaddress of system on which runs this algorithm.
 */
private InetAddress localAddress;
/**
 * port to listen at for incoming route info from neighbors.
 */
int port;
private LinkedBlockingQueue<DatagramPacket> lbq = new LinkedBlockingQueue<DatagramPacket>();

/**
 * Made constructor private to force initialization by specifying port
 * compulsory.
 */
private Router() {
}

/**
 * Constuctor taking port number as parameter and creates a datagramSocket
 * to listen for incoming DatagramPacket on that socket.
 * @param port
 */
public Router(int port) {
    try {
        this.port = port;
        localAddress = InetAddress.getByName("127.0.0.1");
        dSoc = new DatagramSocket(port, localAddress);
    } catch (Exception ex) {
        System.out.println("Error while creating socket : " + ex.getMessage());
    }
    this.start();

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            while (true) {
                try {
                    received_Route_Info(lbq.take());
                } catch (InterruptedException ex) {
                    System.out.println("Error while reading elements from datagram queue");
                }}}});
}

public void setRouterBootInfo(String strNeighboursInfo) {
    String[] strNeighbouringNodes = strNeighboursInfo.split(";");

   for (int i = 0; i < strNeighbouringNodes.length; i++) {

        String[] strNodeIpAndPort = strNeighbouringNodes[i].split(":");

        hmapDirectNeighbours.put(Integer.valueOf(strNodeIpAndPort[0]), Integer.valueOf(strNodeIpAndPort[1]));
        hmapRoutes.put(Integer.valueOf(strNodeIpAndPort[0]), new RouteDetail(null, Integer.valueOf(strNodeIpAndPort[1])));
    }
    propagateChanges();
// entry in Route table....No need for infinity as we creat entry when a node is reachable.
}

@Override
public void run() {
    while (true) {
        try {
            byte[] buf = new byte[250];
            // receive request
            dpackReceive = new DatagramPacket(buf, buf.length);
            dSoc.receive(dpackReceive);
            lbq.put(dpackReceive);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
            dSoc.close();
        } catch (IOException e) {
            e.printStackTrace();
            dSoc.close();
        }
    }


}

/**
 * This method is called for each DatagramPacket received containing new
 * routing information.
 *
 * This method checks whether this packet came from neighboring node
 * (routers) only. If true it applies Distance vector algorithm on data
 * present in datagram packet and due to this information if their is any
 * change in local routing information that it displays current local
 * updated routing information and also sends this updated information to
 * other neighbours only.
 *
 * @param dataPckt
 * @see  #validate_Is_Packet_From_Neighbor(java.net.DatagramPacket)
 * @see #apply_Routing_Algorithm(java.net.DatagramPacket, java.util.HashMap)
 * @see #print_route_info()
 * @see #send_Updates_To_Neighbors(routesInfo)
 */
private void received_Route_Info(DatagramPacket dataPckt) {
    if (dataPckt.getPort() == 4000) {
        setRouterBootInfo(getStringFromBytes(dataPckt));
    } else if (validate_Is_Packet_From_Neighbor(dataPckt)) {
        if (apply_Routing_Algorithm(dataPckt, create_HashMap_Routes(getStringFromBytes(dataPckt)))) {

            // if their is change in routing information.
            propagateChanges();
        }
    }
}

/**
 * Validates whether the Datagram packet received is from the neighbors only.
 * @param datagrampckt DatagramPacket comtaining routing information.
 * @return true if datagrampckt is from neighbors only otherwise false.
 */
private boolean validate_Is_Packet_From_Neighbor(DatagramPacket datagrampckt) {
    return hmapDirectNeighbours.containsKey(Integer.valueOf(datagrampckt.getPort()));
}

/**
 * Returns byte representaion of data contained in DatagramPacket pkt.
 * @param pkt DatagramPacket
 * @return byte representation of data contained in pkt
 */
private String getStringFromBytes(DatagramPacket pkt) {
    String strData = new String(pkt.getData());
    return strData.substring(0, strData.lastIndexOf(';'));
}

/**
 * Applies Distance Vector algorithm using newly received routing information
 * and information presently with this node (Router).
 * @param datagrampckt DatagramPacket containing routing information.
 * @param newRoutes HashMap of routes new information received with
 * destination as key and cost to that destination as value.
 */
private boolean apply_Routing_Algorithm(DatagramPacket dataPckt, HashMap<Integer, Integer> newRoutes) {
    boolean updated = false;
    Integer pktSourse = Integer.valueOf(dataPckt.getPort());

    // Get a set of the routes
    Set<Integer> set = newRoutes.keySet();

    // Get an iterator
    Iterator<Integer> iterator = set.iterator();

    // Display elements.
    while (iterator.hasNext()) {
        Integer key = iterator.next();
        Integer nextHopCost = hmapRoutes.get(pktSourse).getPathCost();
        int optionalCost = newRoutes.get(key) + (nextHopCost == null ? 0 : nextHopCost);
        if (hmapRoutes.containsKey(key)) {
            RouteDetail routeDetail = hmapRoutes.get(key);

            if (routeDetail.getPathCost().compareTo(optionalCost) > 0) {
                routeDetail.setNextHop(pktSourse);
                routeDetail.setPathCost(optionalCost);
                hmapRoutes.put(key, routeDetail);
                updated = true;

            // try to verify above statement
            }
        } else {
            if (!key.equals(port)) {
                RouteDetail newRouteDetail = new RouteDetail(pktSourse, optionalCost);
                hmapRoutes.put(key, newRouteDetail);
                updated = true;
            }
        }
    }

    return updated;
}

/**
 * When internal routing information is chaged, send this information to
 * other neighbors.
 * @param routesInfo byte representaion of routing information.
 */
private void send_Updates_To_Neighbors(byte[] routesInfo) {

    // Get a set of the routes
    Set<Integer> set = hmapDirectNeighbours.keySet();

    // Get an iterator
    Iterator<Integer> iterator = set.iterator();

    // Display elements.
    while (iterator.hasNext()) {
        dpackSend = new DatagramPacket(routesInfo, routesInfo.length, localAddress, iterator.next().intValue());

        try {
            dSoc.send(dpackSend);
        } catch (IOException ex) {
            System.out.println("Error while sending route updates : " + ex.getMessage());
        }
    }
}

/**
 * Parses routeInfo to creat an HashMap based on this informationin the
 * format as HashMap of <<Integer:Destination>,<Integer: Cost to this destination>>
 * @param routeInfo contains routing information as String in the syntax
 * of {<Destination>:<Cost to destination>;}
 * @return Hashmap<<Integer:Destination>,<Integer: Cost to this destination>>
 */
private HashMap<Integer, Integer> create_HashMap_Routes(String routeInfo) {
    HashMap<Integer, Integer> routes = new HashMap<Integer, Integer>();
    String[] straRoute = routeInfo.split(";");

    for (int i = 0; i < straRoute.length; i++) {
        String[] straDestAndCost = straRoute[i].split(":");

        routes.put(Integer.parseInt(straDestAndCost[0]), Integer.parseInt(straDestAndCost[1]));
    }

    return routes;
}

/**
 * Converts current routing information stored as HashMap to String
 * presentation in format as {<Destination>:<Cost to destination>;}
 *
 * @return String representaion of routing information.
 * @see #hmapRoutes.
 */
private String create_String_Of_Routes() {
    StringBuilder strB = new StringBuilder();

    // Get a set of the routes
    Set<Integer> set = hmapRoutes.keySet();

    // Get an iterator
    Iterator<Integer> iterator = set.iterator();

    // Display elements.
    while (iterator.hasNext()) {
        Integer destination = iterator.next();

        strB.append(destination);
        strB.append(":");
        strB.append(hmapRoutes.get(destination).getPathCost());
        strB.append(";");
    }

    return strB.toString();
}

/**
 * Prints the current routing information stored in <code>hmapRoutes</code>
 * to default output stream of this program.
 * @see #hmapRoutes.
 */
public void print_route_info() {
    RouteDetail route;
    StringBuilder builder;

    // PRINT THE CURRENT ROUTING INFO AT THIS NODE
    System.out.println("");
    System.out.println("    TABLE AT NODE WITH PORT  : " + port);
    System.out.println("--------------------------------------------------------------------------------");
    System.out.println("\t\tTo  \t|\t Via\t|\tCost\t\t");
    System.out.println("--------------------------------------------------------------------------------");

    // Get a set of the routes
    Set<Integer> set = hmapRoutes.keySet();

    // Get an iterator
    Iterator<Integer> iterator = set.iterator();

    // Display elements.
    while (iterator.hasNext()) {
        Integer key = iterator.next();

        route = hmapRoutes.get(key);
        builder = new StringBuilder();
        builder.append("\t\t" + key.intValue());
        builder.append("\t|\t" + (route.getNextHop() == null ? "   -" : route.getNextHop()));
        builder.append("\t|\t" + route.getPathCost() + "\t\t");
        System.out.println(builder.toString());
    }
}

/**
 * This class provides details for each destination.
 * It provides detail of cost that will be incurred to reach that
 * destination and next router on that path.
 */

私有类 RouteDetail {

    Integer nextHop;
    Integer pathCost;

    public RouteDetail(Integer nextHop, Integer pathCost) {
        this.nextHop = nextHop;
        this.pathCost = pathCost;
    }

    public Integer getNextHop() {
        return nextHop;
    }

    public void setNextHop(Integer nextHop) {
        this.nextHop = nextHop;
    }

    public Integer getPathCost() {
        return pathCost;
    }

    public void setPathCost(Integer pathCost) {
        this.pathCost = pathCost;
    }
}

private void propagateChanges() {
    print_route_info();
    send_Updates_To_Neighbors(create_String_Of_Routes().getBytes());
}

public static void main(String[] args) {
    new Router(Integer.parseInt(args[0]));
}

}

/* * 文件名:NetworkBoot.java * 公共类名:NetworkBoot * */

导入 java.io.IOException;

导入 java.net.DatagramPacket;

导入 java.net.DatagramSocket;

导入java.net.InetAddress;

/** * * NA1 项目 2009 年春季学期 * @author Sunny jain * * */

公共类 NetworkBoot {

public static void main(String[] args) {
    try {
        DatagramSocket dSoc = new DatagramSocket(4000, InetAddress.getByName("127.0.0.1"));
        String[] sendD = {"4006:3;4007:5;4009:2;", "4005:3;4007:3;4008:6;", "4005:5;4006:3;", "4009:2;4006:6;", "4008:2;4005:2;"};
        for (int i = 0, port = 4005; i < 5; i++) {
            dSoc.send(new DatagramPacket(sendD[i].getBytes(), sendD[i].length(), InetAddress.getByName("127.0.0.1"), port++));
        }
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

}

于 2009-06-14T02:39:08.197 回答
0

我没有在 Java 中做到这一点,但是,您可以(或应该)将多个同时数据报缓冲区传递给套接字(或者使用多个线程,每个线程调用同步接收方法,或者最好使用一个线程调用异步接收方法)不止一次)。

将多个同时的数据报缓冲区传递给套接字的优点是显而易见的:即套接字仍然有一个缓冲区(接收下一个数据报到该缓冲区),即使它已经填充了一个缓冲区(带有前一个数据报)并将该缓冲区传回给你。

您可能会问,“缓冲区将按什么顺序传回给我?” 答案是“没关系”。如果您处理数据报的顺序很重要,那么数据报本身应该包含一个序列号(因为数据报在通过网络路由时可能会出现乱序,无论您是否已经同时将多个传递到本地套接字“同时”收到的结果可能会不按顺序送回给您)。

于 2009-05-09T03:49:18.910 回答
0

DatagramSocket socket = new DatagramSocket(4445, InetAddress.getByName("127.0.0.1")); while (true) { try { // 注意 final .. final byte[] buf = new byte[2000];

    // receive request
    DatagramPacket recvRequest = new DatagramPacket(buf, buf.length);

    socket.receive(recvRequest);

    //Some process of data in datagram
    (new Thread(new Runnable() {
        public void run () {
            // do stuff with data in buf
            ...
        }
    })).start();

} catch (IOException e) {
    e.printStackTrace();
}

}

于 2009-05-09T20:20:03.190 回答
0

值得记住的是 UDP 是有损传输,而尽量减少数据包丢失是一个好主意,您永远不应该假设您会收到每个数据包,(或者数据包将按照您发送它们的顺序到达)

于 2009-05-10T07:13:13.730 回答