Send / Receive MPI-Fortran-Java - java

I have a send / receive implementation in Open-MPI and Java. The goal is to send a Fortran character set to Java. When Java receives this String it prints the following result.
Result send/receive
My Fortran code is:
program simple4
implicit none
include 'mpif.h'
integer ierr,my_rank,size
integer src, dest, tag, position, charSize
integer status(MPI_STATUS_SIZE)
CHARACTER*80 TEXT
call mpi_init(ierr)
call mpi_comm_rank(MPI_COMM_WORLD,my_rank,ierr)
call mpi_comm_size(MPI_COMM_WORLD,size,ierr)
src = 0
dest = 1
tag = 999
if(my_rank.eq.0) then
position = 0
TEXT = "PRO"
call MPI_SEND(TEXT, 3, MPI_CHARACTER, dest, tag, MPI_COMM_WORLD, ierr)
else
print *, "Fortran process ", my_rank
end if
call mpi_finalize(ierr)
end
My Java code is:
....
char[] textChar = new char[3];
MPI.COMM_WORLD.recv(textChar, 3, MPI.CHAR, sourceRank, messageTag);
String text = String.copyValueOf(textChar);
System.out.println("Java - Text receive: " + text);
What would be the problem in my code?
Fortran and Java will not be able to communicate this way? What would be another solution?

The root cause is a Fortran CHARACTER is in ASCII whereas a Java String is in Unicode, so some extra steps are involved.
Here is a snippet of what you could do in Java
byte[] textByte = new byte[3];
MPI.COMM_WORLD.recv(textByte, 3, MPI.BYTE, sourceRank, messageTag);
String text = new String(textByte, java.nio.charset.Charset.forName("UTF-8"));
System.out.println("Java - Text receive: " + text);

Related

Two strings appear to be equal, but they are not

I want to open a file using the argument I get via a socket. When I extract the filename using split(), the file does not open. But when I hardcode the value, it does open.
What am I missing here? I would expect the strings to be equal.
String name = str.split(";")[2];
System.out.println("Filename: " + name);
String path1 = new String("Input_Blatt3/Sample.txt");
String path2 = new String("Input_Blatt3/" + name);
System.out.println("Path1: " + path1);
System.out.println("Path2: " + path2);
System.out.println("path1.equals(path2) = " + path1.equals(path2));
Output:
Path1: Input_Blatt3/Sample.txt
Path2: Input_Blatt3/Sample.txt
path1.equals(path2) = false
There could be unprintable characters hidden in the String.
Use getBytes to get all the characters of a String and print those. You'll probably find something you didn't expect.
You need to iterate over the byte array to print each byte individually, as in the following method:
private static void printBytes(String string) {
System.out.println("printing " + string);
for (byte aByte : string.getBytes()) {
System.out.println( aByte );
}
}
Alternatively you could also replace everything that isn't a printable character with nothing.
There could be some trailing white spaces, which you would not see at the console output.
You can try name.strip() (or trim() if your JDK version is lower 11) to ensure that there's nothing but the file name in the string.
Also, you can find the index of the first mismatching character of these two strings using Arrays.mismatch():
int indexOfMismatch = Arrays.mismatch(str1.toCharArray(), str2.toCharArray());
In case if the strings are equal, indexOfMismatch would be -1.

ANTLR4 no viable alternative; problem with spaces

grammar Hello;
#parser::header {
import java.util.*;
}
#parser::members {
Map<Integer, String> map = new HashMap<Integer, String>();
int A = 0;
int B = 0;
int max = 0;
}
prog
#after {
List<Integer> msgs = new ArrayList<>(map.keySet());
Collections.sort(msgs);
for (int i=0; i< msgs.size(); i++){
System.out.println(map.get(msgs.get(i)));
}
System.out.println("Alice: "+ A +", Bob: "+B);
System.out.println(max);
}
: stat+;
stat: message NL | message;
message: h=T_NUM ':' m=T_NUM ':' s=T_NUM 'A' ':' T_MSG {
String msg = $h.getText() + ":" + $m.getText() + ":" + $s.getText() + " A: " + $T_MSG.getText();
int len = $T_MSG.getText().length();
if (len > max) max = len;
A++;
int id = Integer.parseInt($h.getText()) * 3600 + Integer.parseInt($m.getText()) * 60 + Integer.parseInt($s.getText());
map.put(id, msg);
} | h=T_NUM ':' m=T_NUM ':' s=T_NUM 'B' ':' T_MSG {
String msg = $h.getText() + ":" + $m.getText() + ":" + $s.getText() + " A: " + $T_MSG.getText();
int len = $T_MSG.getText().length();
if (len > max) max = len;
B++;
int id = Integer.parseInt($h.getText()) * 3600 + Integer.parseInt($m.getText()) * 60 + Integer.parseInt($s.getText());
map.put(id, msg);
};
T_NUM: [0-9][0-9];
T_MSG: [A-Za-z0-9.,!? ]+;
NL: [\n]+;
WS : [ \t\r]+ -> skip ; // skip spaces, tabs, newlines
Hello! So I have a task to write grammar and parser in ANTLR4 which recognizes this kind of input:
00:10:11 A: Message 1
23:12:12 B: Message 5
11:12:13 A: Message 2
12:21:12 B: Message 4
11:12:15 A: Message 3
and as an output, it has to sort out messages by time. Now my problem is with spaces. I want to be able to recognize spaces in messages but I get an error:
line 1:6 no viable alternative at input '00:10:11 A'
Alice: 0, Bob: 0
0
When I remove space from the T_MSG token and obviously input it works. But I don't know how to make it work for it to be able to recognize spaces in messages.
Always dump your token stream to see what the Lexer produces for the Parser to consume.
For the first line of your test input, (using grun Hello prog -tokens < Hello.txt), I get:
[#0,0:1='00',<T_NUM>,1:0]
[#1,2:2=':',<':'>,1:2]
[#2,3:4='10',<T_NUM>,1:3]
[#3,5:5=':',<':'>,1:5]
[#4,6:9='11 A',<T_MSG>,1:6]
[#5,10:10=':',<':'>,1:10]
[#6,11:21=' Message 1 ',<T_MSG>,1:11]
[#7,22:22='\n',<NL>,1:22]
[#8,23:22='<EOF>',<EOF>,2:0]
line 1:6 no viable alternative at input '00:10:11 A'
Alice: 0, Bob: 0
0
in particular notice the line
[#4,6:9='11 A',<T_MSG>,1:6]
Your parser isn't seeing the stream of tokens that your parser rules assume it will see.
This is because "11 A" matches the T_MSG Lexer rule. Note: even though the T_NUM rule matches the "11" input, ANTLR's Lexer will use the Lexer rule that consumes the most input, so ANTLR will produce a T_MSG token.
That's why you're getting the observed error.
There are ways using Lexer modes, not skipping WS (which means accounting for all places where WS can occur in your parser rules), or maybe a couple of other techniques.
That said, you're really applying the wrong tool to the job. Reading this input in line by line and applying a Regex with capture groups will be MUCH simpler. There's nothing about your input that requires a full-fledged parser.
IF your push forward with ANTLR, you're probably also much better off just working out the grammar to get the correct parse tree and then using a listener to handle the results. All of the #parser* , prog {...} and parser rule actions, are distractions at best if you're not yet building the correct parse tree.

How to properly parse a tcp packet in java?

I currently have a simple TCP server, which calls a function and passes it the binary TCP payload in the form of a byte array on every new incoming packet, what is the proper way to parse it?
I tried doing it by just slicing it into different byte arrays and processing them separately, but my packets include a variable-length datatype, which I am unable to split from the other data. It really seems like it's not what I should do and I think there is a better way to do it
readVarInt() is a function that parses the variable-length datatype and returns the result and the length of the unparsed datatype in an int[] array
PacketHeader is a class that that has size, id and body fields, id and size are already parsed and the body field contains everything else after the size and id bytes
int[] parsedProtocolVersion = Main.readVarInt(packetHeader.body);
System.out.println(parsedProtocolVersion[0] + ' ' + parsedProtocolVersion[1]);
int[] parsedServerAddressSize = Main.readVarInt( packetHeader.body.subList(parsedProtocolVersion[1], packetHeader.body.size()));
System.out.println("parsed 1 " + parsedServerAddressSize[1] + " " + parsedServerAddressSize[0]);
String parsedServerAddress = String.valueOf(packetHeader.body.subList(parsedServerAddressSize[1], parsedServerAddressSize[0]));
System.out.println("parsed 2");
int parsedServerPort = Integer.parseUnsignedInt((packetHeader.body.subList(parsedServerAddressSize[1]+parsedProtocolVersion[1], parsedServerAddressSize[1]+parsedProtocolVersion[1]+2).toString()));
System.out.println("parsed 3");
int[] parsedNextState = Main.readVarInt(packetHeader.body.subList(parsedServerAddressSize[1]+parsedProtocolVersion[1]+2, packetHeader.body.size()));
System.out.println("parsed 4");
return String.format("%d %s %d %d",parsedProtocolVersion[0], parsedServerAddress, parsedServerPort, parsedNextState[0]);

How will I be able to printout the captured packets using pcap.loop() with a parameter of Pcap.LOOP_INFINITE into the JTextArea?

I'm quite new to JNetPcap and I'm still finding my way around with it, I'm trying to build a Packet sniffer for my project, Lately I'm trying printout packet information into a JTextArea by appending the information from a pcap.loop() that I am using, but when I set the first parameter using a specific integer value let say 5 the pcap.loop() outputs 5 packets that had been captured, Now what I want is to continuously capture and output the packet until I press the button stop. The syntax below shows the Packet handler.
PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {
public void nextPacket(PcapPacket packet, String user) {
// System.out.printf is included to check if my code works in a non GUI fashion
System.out.printf("Received packet at %s caplen=%-4d len=%-4d %s\n",
new Date(packet.getCaptureHeader().timestampInMillis()),
packet.getCaptureHeader().caplen(), // Length actually captured
packet.getCaptureHeader().wirelen(), // Original length
user // User supplied object
);
Date a = new Date(packet.getCaptureHeader().timestampInMillis());
int b = packet.getCaptureHeader().caplen();
int c = packet.getCaptureHeader().wirelen();
String d = user;
pcktTextArea.append("Received packet at " + a + " caplen=" + Integer.toString(b) + " len=" + Integer.toString(b) + user + "\n" );
pcktTextArea.setForeground(Color.red);
pcktTextArea.setFont(font);
}
};
Now this bit here is my pcktTextArea which I use append to print out the information in the textarea:
pcktTextArea.append("Received packet at " + a + " caplen=" + Integer.toString(b) + " len=" + Integer.toString(b) + user + "\n" );
pcktTextArea.setForeground(Color.red);
pcktTextArea.setFont(font);
And Finally the Pcap.loop which I am having trouble with, if I replace that i with let say 5 it does get printed in the JTextArea but when I put the Pcap.LOOP_INFINTE it only prints the information through console but not in GUI JTextArea:
int i = Pcap.LOOP_INFINITE;
pcap.loop(i , jpacketHandler, " ");
/***************************************************************************
* Last thing to do is close the pcap handle
**************************************************************************/
pcap.close();
Is it because it has to finish the loop before printing the information out in the Textarea?
I assume you run the code in a thread. Use
SwingUtilities.invokeAndWait to call the pcktTextArea.append() code

Receive string from processing to arduino

I want to receive a string from processing to arduino. I am writing a string(Basically an array of single digits in the form of string eg: <0213> is an array: 0 2 1 3). I am able to write it to port but how do I receive it on arduino? Following code is to send to arduino.
int[] send={0,2,3,1};
myPort =new Serial(this,"/dev/ttyACM0", 9600);
String theStg = "<" + nf(send[0], 3) +
" " + nf(send[1], 3) +
" " + nf(send[2], 3) +
" " + nf(send[3], 3) +
">";
myPort.write(theStg);
if you were using a string of char*, rather than the String Class, then you could use avrlibc's strtok() command.
This has been addressed previously(click here)
And here is a nice function you can simply add to your code to do the equivalent of the strtok(), but on a String object.

Categories

Resources