使用Java进行网络连接方面的新功能。因此,在用Java构建自己的网络UDP协议时遇到了问题。该程序应读取两个文件,即itc-1和itc-2,但面临的问题是我的程序仅读取itc-1并在读取itc-2时摇摇欲坠,我不知道问题所在!我不能在这里放置所有代码,因为它太长了,所以我认为这个课程中的问题您可以检查一下!!
客户端类:
public class Client {
public static final String MESSAGETONODE = "message to node";
public static final String CHECK = "checking message";
public static final String ACK = "ACK message";
public static final String CHECKMESSAGE = "Are you alive?";
public static final String ACKMESSAGE = "I'm okay";
public static final String DEATHNOTE = "Death note";
public static final String BIRTHCERT = "Birth cert";
public static ArrayList<Node> linkNode = new ArrayList<Node>();
private static int sourceNode;
static int destPort;
static int destNode;
private int neighborCounts;
private static int sourcePort;
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
private static BlockingQueue<QueueMessage> blockingQueue;
private static ArrayList<BlockingQueue<QueueMessage>> ACKQueue;
private static NetworkLayer networkLayer;
public Client(int nodeID, String itcFile) throws IOException {
blockingQueue = new ArrayBlockingQueue<>(100);
ACKQueue = new ArrayList<>();
assignFromFile(itcFile);
networkLayer = new NetworkLayer(itcFile, nodeID, linkNode);
neighborCounts = networkLayer.getNeighborsCount();
for (int i = 0; i < neighborCounts; ++i) ACKQueue.add(new ArrayBlockingQueue<>(100));
System.out.println(nodeID + " " + itcFile);
sourceNode = nodeID;
for (Node n : linkNode) {
if (n.getNodeID() == nodeID)
sourcePort = n.getPortNumber();
}
startServer(sourcePort);
startSender();
messagePrompt(reader, blockingQueue);
for (int i = 0; i < neighborCounts; ++i)
networkLayer.checkNeighbors(blockingQueue, ACKQueue.get(i), i);
}
public void messagePrompt(BufferedReader reader, BlockingQueue<QueueMessage> blockingQueue) {
(new Thread(() -> {
while (true) {
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter message: ");
String message = null;
try {
message = inFromUser.readLine();
} catch (IOException e) {
e.printStackTrace();
}
System.out.print("Enter destination node: ");
int destNode = 0;
try {
destNode = Integer.parseInt(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
// TODO this is supposed to be wrapped in headers to avoid what I'm doing in this next line
message = MESSAGETONODE + " " + destNode + " " + sourceNode + " " + message;
blockingQueue.add(new QueueMessage(Client.MESSAGETONODE, message, destNode, sourceNode, getTimeInMS()));
}
})).start();
}
public static void assignFromFile(String itcFile) throws FileNotFoundException {
Scanner docScan = new Scanner(new File(itcFile + ".txt"));
String data;
while (docScan.hasNextLine()) {
data = docScan.nextLine();
String[] word = data.split(" ");
final Node NODE = new Node(Integer.parseInt(word[0]), word[1], Integer.parseInt(word[2]),
Integer.parseInt(word[3]), Integer.parseInt(word[4]), Integer.parseInt(word[5]));
linkNode.add(NODE);
}
}
public static void startSender() {
(new Thread() {
@Override
public void run() {
try {
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
for (Node n : linkNode) {
if (destNode == n.getNodeID())
destPort = n.getPortNumber();
}
DatagramSocket socket = new DatagramSocket();
DatagramPacket msg = new DatagramPacket(new byte[0], 0, InetAddress.getByName("localhost"), destPort);
while (true) {
QueueMessage queueMessage = blockingQueue.take();
String type = queueMessage.getMessageType();
byte[] bbuf;
if (type != null) {
int destNode = queueMessage.getDestinationNID();
int destPort = networkLayer.routeMessage(queueMessage);
if (destPort == NetworkLayer.INF) continue;
if (queueMessage.getMessage() == null) break;
TransportLayer transportLayer = new TransportLayer(queueMessage.getSourceNID(),
networkLayer.getNodePort(queueMessage.getSourceNID()),
queueMessage.getDestinationNID(), destPort, queueMessage.getMessage());
String message = transportLayer.sendData(queueMessage.getDestinationNID(),
queueMessage.getMessage());
transportLayer.setMessage(message);
bbuf = message.getBytes();
msg.setData(bbuf);
msg.setLength(message.length());
msg.setPort(destPort);
try {
socket.send(msg);
} catch (IOException ioe) {
System.err.println("send() failed");
return;
}
}
}
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public static void startServer(int port) {
new Thread() {
@Override
public void run() {
ServerSocket ss;
ServerSocket destSocket;
DatagramSocket dSocket;
int bufSize = 512;
try {
dSocket = new DatagramSocket(port);
} catch (SocketException se) {
System.err.println("cannot create socket with port: " + port);
return;
}
try {
dSocket.setSoTimeout(15000);
} catch (SocketException se) {
System.err.println("Socekt exception: timeout not set");
}
DatagramPacket msg = new DatagramPacket(new byte[bufSize], bufSize);
while (true) {
try {
msg.setLength(bufSize);
dSocket.receive(msg);
} catch (SocketTimeoutException ste) {
System.err.println("response timed out");
continue;
} catch (IOException ioe) {
System.err.println("Bad receive");
break;
}
String str = new String(msg.getData(), 0, msg.getLength());
TransportLayer transportLayer = new TransportLayer();
transportLayer.setMessage(str);
int checksum = transportLayer.receiveChecksum();
transportLayer.receiveHeaders();
str = transportLayer.getMessage();
if (str.startsWith(CHECKMESSAGE)) {
int senderNode = Integer.parseInt(str.substring(CHECKMESSAGE.length() + 1));
blockingQueue.add(new QueueMessage(ACK, ACKMESSAGE + " " + sourceNode, senderNode,
sourceNode, getTimeInMS()));
} else if (str.startsWith(ACKMESSAGE)) {
int senderNode = Integer.parseInt(str.substring(ACKMESSAGE.length() + 1));
int neighborIndex = networkLayer.getNeighborIndex(senderNode);
ACKQueue.get(neighborIndex).add(new QueueMessage(ACK, ACKMESSAGE, 0, sourceNode,
getTimeInMS()));
} else {
if (str.startsWith(MESSAGETONODE)) {
Scanner stringstream = new Scanner(str);
String type, actualMessage;
int dest, src;
type = stringstream.next();
type = stringstream.next();
type = stringstream.next();
dest = stringstream.nextInt();
src = stringstream.nextInt();
actualMessage = stringstream.next();
if (dest != sourceNode)
blockingQueue.add(new QueueMessage(MESSAGETONODE, str, dest, src, getTimeInMS()));
else {
System.err.println("message from <" + msg.getAddress().getHostAddress() + ","
+ msg.getPort() + ">");
System.out.println(actualMessage);
System.out.println("Checksum received = " + checksum);
}
} else {
Scanner stringstream = new Scanner(str);
String type = stringstream.next();
type = stringstream.next();
int nodeID = stringstream.nextInt();
int src = stringstream.nextInt();
int TTL = stringstream.nextInt();
int neighborIndex = networkLayer.getNeighborIndex(src);
if (str.startsWith(DEATHNOTE)) {
System.out.println("Node " + nodeID + " is dead");
networkLayer.setNodeDead(nodeID);
if (TTL > 1) {
for (int i = 0; i < networkLayer.getNeighborsCount(); ++i)
if (i != neighborIndex)
blockingQueue.add(new QueueMessage(DEATHNOTE, DEATHNOTE + " " +
nodeID + " " + src + " " + Integer.toString(TTL - 1),
networkLayer.getNeighborNID(i), sourceNode, getTimeInMS()));
}
} else {
System.out.println("Node " + nodeID + " is alive");
networkLayer.setNodeAlive(nodeID);
if (TTL > 1) {
for (int i = 0; i < networkLayer.getNeighborsCount(); ++i)
if (i != neighborIndex)
blockingQueue.add(new QueueMessage(BIRTHCERT, BIRTHCERT + " " +
nodeID + " " + src + " " + Integer.toString(TTL - 1),
networkLayer.getNeighborNID(i), sourceNode, getTimeInMS()));
}
}
}
}
}
}
}.start();
}
public static long getTimeInMS() {
return System.currentTimeMillis();
}
}
主类:
import java.io.*;
public class Main {
public static void main(String[] args) throws NumberFormatException, IOException {
Client client;
if(args.length != 2)
System.out.println("Usage: java Client host port");
else
client = new Client(Integer.parseInt(args[0]), args[1]); // run as java Main (nodeID) (itc-[number])
//java Main 1 itc-1
}
}
网络层
import java.io.*;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class NetworkLayer {
private final int threshold = 5000;
private final int waitingTime = 2000;
public static final int INF = (int) 1e9;
private String itcFile;
private int nNodes;
private int nodeID;
private ArrayList<Node> linkNode;
private int[] nextHop;
private int[] shortestPath;
private List<List<Neighbor>> adjList;
private int aliveMsk = 4095;
private int tmpMsk = 4095;
public NetworkLayer(String itcFile, int nodeID, ArrayList<Node> linkNode) throws FileNotFoundException {
this.itcFile = itcFile;
this.nNodes = 0;
this.nodeID = nodeID;
this.linkNode = linkNode;
init();
nextHop = new int[nNodes + 1];
shortestPath = new int[nNodes + 1];
setupRoutingTable();
}
private void init() throws FileNotFoundException {
this.nNodes = 0;
Scanner scanner = new Scanner(new File(itcFile + ".txt"));
while (scanner.hasNextInt()) {
this.nNodes++;
int ID = scanner.nextInt();
String name = scanner.next();
int port = scanner.nextInt();
int n1 = scanner.nextInt();
int n2 = scanner.nextInt();
int mtu = scanner.nextInt();
}
linkNode.add(new Node(0, "", 0, 0, 0, 0));
Collections.sort(linkNode, (lhs, rhs) -> lhs.getNodeID() < rhs.getNodeID() ? -1 : 1);
fillAdjList();
}
private boolean notPresentInAdjList(int x, int y) {
for (Neighbor n : adjList.get(x)) if (n.getID() == y) return false;
return true;
}
private void addToAdjList(int x, int y) {
if (notPresentInAdjList(x, y)) adjList.get(x).add(new Neighbor(y));
}
private void fillAdjList() {
adjList = new ArrayList<>();
for (int i = 0; i < nNodes + 5; ++i) adjList.add(new ArrayList<>());
// System.out.println(adjList.size());
for (Node n : linkNode) {
addToAdjList(n.getNodeID(), n.getNodeOne());
addToAdjList(n.getNodeOne(), n.getNodeID());
addToAdjList(n.getNodeID(), n.getNodeTwo());
addToAdjList(n.getNodeTwo(), n.getNodeID());
}
// printAdjList();
}
private void printAdjList() {
System.out.println("\nSTARTED PRINTING");
for (Neighbor i : adjList.get(nodeID)) System.out.print(i.getID() + " ");
System.out.println("\nENDED PRINTING");
}
public void setupRoutingTable() {
Arrays.fill(nextHop, INF);
Arrays.fill(shortestPath, INF);
dijkstra(nodeID);
// System.out.println("BACK ");
displayRoutingTable();
}
private void dijkstra(int src) {
PriorityQueue<pqNode> pq = new PriorityQueue<>(1, Comparator.comparingInt(pqNode::getCost));
nextHop[src] = src;
shortestPath[src] = 0;
pq.add(new pqNode(0, src));
while (!pq.isEmpty()) {
int top = pq.peek().getCurNode();
pq.poll();
for (Neighbor n : adjList.get(top)) {
int node = n.getID();
if (isNodeAlive(node) && shortestPath[top] + 1 < shortestPath[node]) {
shortestPath[node] = shortestPath[top] + 1;
if (nextHop[top] == src) nextHop[node] = node;
else nextHop[node] = nextHop[top];
pq.add(new pqNode(shortestPath[node], node));
}
}
}
}
public void displayRoutingTable() {
for (int x : shortestPath) System.out.print(x + " ");
System.out.println();
System.out.println("\n----------------\n");
for (int x : nextHop) System.out.print(x + " ");
System.out.println();
System.out.println();
}
public void checkNeighbors(BlockingQueue<QueueMessage> blockingQueue, BlockingQueue<QueueMessage> ACKQueue,
int neighborIndex) {
(new Thread(() -> {
Neighbor neighbor = adjList.get(nodeID).get(neighborIndex);
while (true) {
// boolean changes = false;
long curTime = getTimeInMS();
if (neighbor.getSentMsg()) {
if (curTime - neighbor.getLastCheckTime() > waitingTime) {
neighbor.setSentMsg(false);
// sentMsg1 = false;
if (neighbor.getIsAlive()) {
System.out.println("Node " + neighbor.getID() + " is dead");
neighbor.setIsAlive(false);
// changes = true;
setNodeDead(neighbor.getID());
// eg: Death note 2(node ID) 4(TTL)
for (Neighbor n : adjList.get(nodeID))
if (neighbor.getID() != n.getID()) {
blockingQueue.add(new QueueMessage(Client.DEATHNOTE, Client.DEATHNOTE + " "
+ neighbor.getID() + " " + nodeID + " 4", n.getID(), nodeID,
getTimeInMS()));
}
}
} else {
try {
QueueMessage message = ACKQueue.poll(100, TimeUnit.MILLISECONDS);
if (message != null) {
if (message.getOriginatingTime() < neighbor.getLastCheckTime()) continue;
neighbor.setSentMsg(false);
if (!neighbor.getIsAlive()) {
System.out.println("Node " + neighbor.getID() + " is alive");
neighbor.setIsAlive(true);
// changes = true;
setNodeAlive(neighbor.getID());
// eg: Birth cert 2(node ID) 4(TTL)
for (Neighbor n : adjList.get(nodeID))
if (neighbor.getID() != n.getID()) {
blockingQueue.add(new QueueMessage(Client.BIRTHCERT,
Client.BIRTHCERT + " " + neighbor.getID() + " " + nodeID
+ " 4", n.getID(), nodeID, getTimeInMS()));
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
if (curTime - neighbor.getLastCheckTime() > threshold) {
neighbor.setSentMsg(true);
neighbor.setLastCheckTime(curTime);
blockingQueue.add(new QueueMessage(Client.CHECK, Client.CHECKMESSAGE + " " + nodeID,
neighbor.getID(), nodeID, getTimeInMS()));
}
}
}
})).start();
}
public void setNodeAlive(int NID) {
this.tmpMsk |= (1 << NID);
}
public void setNodeDead(int NID) {
this.tmpMsk &= ~(1 << NID);
}
public int getNeighborNID(int neighbor) {
return adjList.get(nodeID).get(neighbor).getID();
}
public long getTimeInMS() {
return System.currentTimeMillis();
}
public boolean isNodeAlive(int NID) {
return ((tmpMsk >>> NID) & 1) == 1;
}
public int routeMessage(QueueMessage queueMessage) {
if (aliveMsk != tmpMsk) {
// System.out.println("ALIVE MSK " + aliveMsk);
// System.out.println("TMP MSK " + tmpMsk);
aliveMsk = tmpMsk;
setupRoutingTable();
}
int destNode = queueMessage.getDestinationNID();
if (queueMessage.getMessageType() == Client.MESSAGETONODE) {
if (nextHop[destNode] == INF) return INF;
return getPort(nextHop[destNode]);
}
// System.out.println(destNode + " " + getPort(destNode));
return getPort(destNode);
}
private int getPort(int i) {
return linkNode.get(i).getPortNumber();
}
public int getNeighborsCount() {
return adjList.get(nodeID).size();
}
public int getNeighborIndex(int senderNode) {
for (int i = 0; i < getNeighborsCount(); i++)
if (adjList.get(nodeID).get(i).getID() == senderNode) return i;
return 0;
}
public int getNodePort(int sourceNID) {
return linkNode.get(sourceNID).getPortNumber();
}
}