I'm looking at the RTI DDS add-in for Excel, and I'm trying to rewrite the Hello_simple HelloPublisher.java example that comes with it to publish a string, and get Excel to pick it up.
Everything works, apart from displaying the value of the string I feed it. (It picks up the time the message was sent, and all the other meta-data just fine)
My code looks something like this:
public class Publish {
public static void main(final String[] args){
// Create the DDS Domain participant on domain ID 123
final DomainParticipant participant = DomainParticipantFactory.get_instance().create_participant(
123, //Domain ID
DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT,
null, // Listener
StatusKind.STATUS_MASK_NONE);
if (participant == null) {
System.err.println("Unable to create domain participant");
return;
}
// Create the topic "Message" for the String type
final Topic topic = participant.create_topic(
"Message",
StringTypeSupport.get_type_name(),
DomainParticipant.TOPIC_QOS_DEFAULT,
null, // listener
StatusKind.STATUS_MASK_NONE);
if (topic == null) {
System.err.println("Unable to create topic.");
return;
}
// Create the data writer using the default publisher
final StringDataWriter dataWriter =
(StringDataWriter) participant.create_datawriter(
topic,
Publisher.DATAWRITER_QOS_DEFAULT,
null, // listener
StatusKind.STATUS_MASK_NONE);
if (dataWriter == null) {
System.err.println("Unable to create data writer\n");
return;
}
System.out.println("Ready to write data.");
System.out.println("When the subscriber is ready, you can start writing.");
System.out.print("Press CTRL+C to terminate or enter an empty line to do a clean shutdown.\n\n");
final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
while (true) {
System.out.print("Please type a message> ");
final String value = reader.readLine();
if (value == null) {break;}
dataWriter.write(value, InstanceHandle_t.HANDLE_NIL);
if (value.equals("")) { break; }
}
} catch (final IOException e) {e.printStackTrace();
} catch (final RETCODE_ERROR e) {e.printStackTrace();}
System.out.println("Exiting...");
participant.delete_contained_entities();
DomainParticipantFactory.get_instance().delete_participant(participant);
}
}
The call I make in Excel to display the value is
=RTD("dds2excel.connect",,"TYPE:DDS::String","TYPENAME:DDS::String","TOPIC:Message","FIELD:value")
(Auto-generated by the RTI add-in)
I'm not very familiar with RTI and DDS yet, but I have a feeling Excel doesn't want to pick up the actual contents of this data because it thinks it doesn't belong to it? Hence why it only acknowledges the meta-data for the domain that it's listening to.
Any pointers would be greatly appreciated.
Related
I need your help, I am new in Java
I need to read a flat file with 5 different of records
the way to differentiate each record is the first characters, after that I have the idea to move to an 5 different array to play with with the data inside.
example
120220502Name Last Name1298843984 $1.50
120220501other client 8989899889 $23.89
2Toronto372 Yorkland drive 1 year Ontario
512345678Transfer Stove Pay
522457839Pending Microwave Interactive
any help will quite appreciated
Break the problem into chunks. The first problem is reading the file:
try (BufferedReader reader = new BufferedReader(new FileReader("path/to/file"))) {
parseData(reader); //method to do the work.
} catch (IOException e) {
e.printStackTrace();
}
Then you need to decide what kind of record it is:
public void parseData(BufferedReader input) throws IOException {
for (String line = input.readLine(); line != null; line = input.readLine()) {
if (line.startsWith("1")) {
parseType1(line);
} else if (line.startsWith("2")) {
parseType2(line);
} else if (line.startsWith("5")) {
parseType5(line);
} else {
throw new Exception("Unknown record type: " + line.charAt(0));
}
}
}
Then you'll need to create the various parseTypeX method to handle turning the text into usable chunks and then into classes.
public Type1Record parseType1(String data) {
//create a Type1Record
Type1Record record = new Type1Record();
//split the string something like
String [] fields = data.split("\\s+");
//Assign those chunks to the record
record.setId(fields[0]);
record.setFirstName(fields[1]);
record.setLastName(fields[2]);
record.setTotal(fields[3]); //if you want this to be a real number, you'll need to remove the $
}
Repeat the process with the other record types. You'll likely need to group records together, but that should be easy enough.
I am developing a simple distributed ledger. I want to be able to start nodes on different ports, that could communicate with eachother. Each programme then would have a file, where it would write newly discovered nodes.
At first, only the most reliable nodes are hardcoded into that file.
Here is procedurally what happens:
1) I start a new node, which starts a HTTP server (I use com.sun.HttpServer). The server has a GetAddress handler, which listens to requests that go to the specified URI. It then gets the IP and PORT (which is specified in URI query params), acquires a semaphore for a known_nodes.txt file, and writes the newly received peer address to that file, if it's not already there, and send the contents of newly updated file as a json list back to the requester.
2) Within my Node class (which, as mentioned earlier, starts a HTTPServer on a separate thread), I create a ScheduledExecutorService and give it a runnable to be run every few seconds, whose job will be to connect to the URLs present in the known_nodes.txt file, and ask them for their known_nodes. If we received nodes that were not previously present in our known_nodes file, we overwrite our file.
NOW!
If I start a node, and try to request it from the browser, everything goes as planned - we receive a request, write it to our file, then our runnable will try to connect to the address specified in request. If we caught a SocketTimeoutException, we remove the address from our known_nodes.txt file.
The problem arises, when I start two nodes, running let's say on port 8001 and 8002. Please note, that each node has its own known_nodes file.
What happens, is that one of the nodes will stop running the DiscoverAddresses task, the other one won't. So effectively, one nodes stopped receiving requests.
NB! The node that will stop its scheduledtask will STILL send at least ONE discovering request, and then will die/block(?).
Here is the code for the runnable task:
#Override
public void run() {
log.info("still running ");
PeerAddressesHolder inactiveNodes = new PeerAddressesHolder();
ApplicationConfiguration appConf = ApplicationConfiguration.getInstance();
for (PeerAddress peerAddress : knownNodes.getAddresses()) {
if (isSameNode(peerAddress)) {
continue;
}
String urlString = String.format("http://%s:%s%s?myport=%d", peerAddress.getIP(), peerAddress.getPort(), Constants.GET_ADDRESS, myPort);
try {
StringBuilder result = new StringBuilder();
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
try (InputStream connInputStream = conn.getInputStream();
InputStreamReader ir = new InputStreamReader(connInputStream);
BufferedReader br = new BufferedReader(ir)){
String line;
while ((line = br.readLine()) != null) {
result.append(line).append('\n');
}
} catch (Exception e) {
log.warn("Couldn't read from connection input stream",e);
}
PeerAddressesHolder peerAddressesHolder = gson.fromJson(result.toString(), PeerAddressesHolder.class);
boolean fetchedNew = false;
for (PeerAddress fetchedAddress : peerAddressesHolder.getAddresses()) {
if (!isValidAddress(peerAddress)) {
log.warn("Peer has sent us a null-address. It will be ignored.");
return;
}
if (!knownNodes.contains(fetchedAddress)) {
knownNodes.addAddress(fetchedAddress);
fetchedNew = true;
}
}
if (fetchedNew) {
FileUtils.writeToFile(appConf.getKnownNodesFilePath(), gson.toJson(knownNodes), false);
}
} catch (SocketTimeoutException e) {
if (appConf.getMostReliableNodes().contains(peerAddress)) {
log.warn("Most reliable node not available: " + peerAddress);
} else {
inactiveNodes.addAddress(peerAddress);
log.warn("Connection timeout from " + peerAddress + ". It will be removed.");
}
} catch (Exception e) {
log.warn("Couldn't discover new addresses." + e);
}
}
try {
knownNodes.removeAll(inactiveNodes.getAddresses());
FileUtils.writeToFile(appConf.getKnownNodesFilePath(), gson.toJson(knownNodes), false);
} catch (IOException ioe) {
log.warn("Couldn't write to file after deleting dead node", ioe);
}
}
And here is how I start it upon Node creation.
public NetworkNode(int port) {
this.appConf = ApplicationConfiguration.getInstance();
this.port = port;
log.info("Starting a new node on port " + port);
try {
this.knownNodes = FileUtils.createPeerAddressesList(appConf.getKnownNodesFilePath());
} catch (Exception e) {
log.error("Error while trying to construct a list of peer addresses from file content on path: " + appConf.getKnownNodesFilePath());
}
scheduledExecutorService = Executors.newScheduledThreadPool(4);
scheduledExecutorService.scheduleAtFixedRate(new DiscoverAddressesTask(knownNodes, this.port), 3, 4, TimeUnit.SECONDS);
Methods dealing with file reading/writing are all done using try-with-resources construct, so my initial idea that the runnable stops because of some unclosed streams is probably not valid.
I have built a Spring CLI app which communicates with a server in an async fashion. The server was given, I did not create it, basically my app is required to open a TCP socket and send a JSON through it, then it sends back a JSON. It is mandatory not to use CLI parameters, but instead in the callback of the request I want to show the user a set of options for which he needs to select by inserting the corresponding number on the CLI. Most probably I'm not doing right something, because after entering the command, I see spring> on the console (this is an expected behavior) and it will block the async callback unless I press something (nothing is printed to the CLI when I receive the callback unless I press a bunch of enters - this is unexpected). To read from the console so far I used JLine's command line, what I would like to achieve is that when I get the response from the server and the callback is served, the console is given to the thread on which the callback is running (I instantly print the contents of the callback to the console, and I'm able to read the input without any tricks).
Some code:
public void runReceiver(){
receiverThread = new Thread(() -> {
byte[] digit = null;
int nb;
Iterator<CommandListener> it;
CommandListener listener;
String message;
List<CommandListener> listenersToRemove = new ArrayList<>();
while (true) {
try {
nb = communicatorInput.readInt();
digit = new byte[nb];
communicatorInput.readFully(digit);
} catch (IOException e) {
e.printStackTrace();
}
it = listeners.iterator();
while (it.hasNext()){
listener = it.next();
if (digit != null && digit.length > 0) {
message = new String(digit);
// the message was not acknowledged
if(message.contains("NACK")){
try {
listener.onError(message);
if (listener.isDone()) {
listenersToRemove.add(listener);
}
} catch (Exception e){
e.printStackTrace();
}
} else try {
listener.onCompleted(message);
} catch (InvalidObjectException e){
Main.logger.debug(String.format("Response could not be parsed as %s", listener.getCommandType()));
} catch (Exception e){
e.printStackTrace();
}
if (listener.isDone()) {
listenersToRemove.add(listener);
}
}
}
listeners.removeAll(listenersToRemove);
}
}, "receiverThread");
receiverThread.setDaemon(true);
receiverThread.start();
Then a CLI command (it expects no input here):
#CliCommand(value="start", help = "Starts stuff")
public void start() throws IOException, InterruptedException {
// this method is passed to the thread with the listener
getAvailabilities().updateAvailabilities("all", "all", "all", someListener);
}
And the callback for that listener:
someListener = new CommandListener() {
private String source = "Start some listener";
#Override
public void onCompleted(String r) throws IOException {
System.out.println("Which would you like to start?");
getAvailabilities().printAvailableBrands();
String brandNumber = "";
while(Objects.equals(brandNumber, "")){
System.out.println("Please enter the number of the Brand: ");
//when the callback arrives here I still only see ">spring:" and I get nothing printed on the console
brandNumber = cr.readLine();
if(!isInputAllowed(brandNumber, getAvailabilities().AvailableBrands.size())){
brandNumber = "";
}
}
BrandName = getAvailabilities().AvailableBrands.get(Integer.parseInt(brandNumber) - 1);
//updating the availabilities narrows down the things I list to the console, so I send an update after every selection
getAvailabilities().updateAvailabilities("all", BrandName, "all", getInterfaceListener);
done = true;
}
This might slightly connect to the issue that sometimes while debugging the CLI in Idea, it gets whacky inputs, eg. when I insert start it says No such command as ar, and if I press enter again, it'll say (some of) the rest: No such command as stt.
The problem is here:
if (listener.isDone()) {
listenersToRemove.add(listener);
}
If you want your listeners to be executed asynchronously you should not check their completion right away on the same thread as it will most likely return false.
The issue you might be having is that your listeners schedule some task but have no time to finish it as you immediately remove them after the loop:
listeners.removeAll(listenersToRemove);
It is very hard to tell what your logic is but I guess in the next while iteration your list is empty.
I want to change the settings of a PROROUTE wireless cellular router (H685) from the web application.
The only way to change the settings, is to login to the router via telnet and change a file in the editor (i.e. vi) and reboot.
I want to do it programmatically from server side using JAVA,
I can connect to the router and send command, using TelnetClient
Here is the sample code to connect to the router via telnet and send command
public class Test
{
private TelnetClient telnet = new TelnetClient();
private InputStream in;
private PrintStream out;
private String prompt = "#";
public Test(String server, String user, String password) {
try {
// Connect to the specified server
telnet.connect(server, 23);
// Get input and output stream references
in = telnet.getInputStream();
out = new PrintStream(telnet.getOutputStream());
// Log the user on
readUntil("Login:");
write(user);
readUntil("Password:");
write(password);
// Advance to a prompt
readUntil(prompt + " ");
} catch (Exception e) {
e.printStackTrace();
}
}
public String readUntil(String pattern) {
try {
char lastChar = pattern.charAt(pattern.length() - 1);
StringBuffer sb = new StringBuffer();
boolean found = false;
char ch = (char) in.read();
while (true) {
System.out.print(ch);
sb.append(ch);
if (ch == lastChar) {
if (sb.toString().endsWith(pattern)) {
return sb.toString();
}
}
ch = (char) in.read();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void write(String value) {
try {
out.println(value);
out.flush();
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
}
}
public String sendCommand(String command) {
try {
write(command);
return readUntil(prompt + " ");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void disconnect() {
try {
telnet.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
Test telnet = new Test("192.168.1.1", "username", "pwd");
telnet.sendCommand("ls");
telnet.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
But I have to update the file in the editor.
Send command to open the file in vi
$vi /flash/.disable_fun_list
function_dtu:
function_wifi:
function_gps:
.
.
.
.
function_wifi:on (this line needs to be changed)
and then send command to restart the router.
$reboot
Any idea, how this can be done.
What you're thinking to do sounds a terrible idea.
I feel there is no need to open this file in vi editor. In such cases, people generally suggest to create a temporary file and replace it with the original.
Suggested approach :
Open the file which you want to modify using BufferedReader on top of FileReader.
Modify the string, if you've to replace the currently read line; if not, then simply proceed to step 3.
Now, once you've string ready(whether changed OR unchanged) to be written to a file, then create a temporary file, and write the read string(line) to this temporary file.
Once, you're done with all the line of the original file, then close the BufferedReader, and delete(or, better rename to something else) the original file. Rename the temp file to the original filename, and move this temp file to the location of the original file from where you've copied(and modified) the content!
Code should flow like :
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader("C:\\testing.txt"));
while ((sCurrentLine = br.readLine()) != null) {
//Step 2 : do modification with the string read
//Step 3 : write the final modified string inside a temp file.
// Step 4 : close the br, and rename/delete the old file; rename the temp file to this original file.
}
you can use vi from command line without actually opening the vi as an app
you can pass args to vi to do a string replace for what you need
and you can pass args to save the file, plus the file path of course.
so you might end up executing this command via telnet connection
vi -c "%s/function_wifi:on/function_wifi:off/g|wq" /path/to/config/file
this will replace the string function_wifi:on with function_wifi:off and save the file.
simply then send a reboot command.
for more check this link
change above program to
private String prompt = ">";
instead of
private String prompt = "#";
I am trying to create a messenger program and have successfully set up client-server connections using sockets. However I am finding it difficult to code the process of having several clients communicating simultaneously. Shown in the code below is the methods for the chats that are held within a ClientThread class that regulates the interaction between client and server using threads stored in a shared ArrayList. How would you implement the code for multiple peer-to-peer chats here?
startChat method:
public void startChat()
{
// start the convo!
// first of all the user chooses who to speak to
// starts a loop until user enters a valid username or 'Group'
String line = "";
boolean validCommand = false;
while(validCommand == false)
{
try {
line = in.readLine();
} catch (IOException e) {
System.out.println("Problem reading reply about user chat");
}
if(line.equalsIgnoreCase("Group"))
{
validCommand = true;
chatAll(); // an integer of negative one starts a chat with everyone
}
else
{
synchronized(this){
// find user
for(int i = 0; i < threads.size(); i++)
{
if(threads.get(i) != null && threads.get(i).username != null)
{
if(threads.get(i).username.equals(line)) // means that we have found the index of the thread that the client wants to speak to
{
/*// START : BETWEEN THESE CAPITALISED COMMENTS IS MY ATTEMPT TO INITIATE TWO WAY CHAT
int thisIndex = -1;
for(int j = 0; j < threads.size(); j++) // gets the index of this thread object in the array
{
if(threads.get(j) == this)
{
thisIndex = j;
// out.println(j);
}
}
if(thisIndex != -1)
{
threads.get(i).out.println(username + " is trying to connect");
threads.get(i).processChat(thisIndex); // this is the line causing the problem!
}
// END : BETWEEN THESE CAPITALISED COMMENTS IS MY ATTEMPT TO INITIATE TWO WAY CHAT */
threads.get(i).out.println(username + " is trying to connect");
out.println("Chat with " + threads.get(i).username);
processChat(i);
validCommand = true;
}
// if the command is not group and not a username, it is not valid and we ask the user to re-enter
else if(i == threads.size() - 1)
{
out.println("This command is not valid, please re-enter");
}
}
}
} // end of synchronised bit
} // end of else statement
} // end of while loop
}
allChat method:
void chatAll()
//for the purpose of group chat
{
out.println("Group chat initiated");
boolean d = true;
while(d == true)
{
String message = "";
try {
message = in.readLine();
} catch (IOException e) {
System.out.println("Can't read line from client");
}
if(message.contains("goodbye") == true)
{
d = false;
}
else
{
synchronized(this)
{
for(int j = 0; j < threads.size(); j++)
{
if(threads.get(j) != null)
{
threads.get(j).out.println(username + ": " + message);
}
}
}
}
}
}
processChat method:
void processChat(int i)
//for the purpose of talking to pre-defined user
{
boolean d = true;
while(d == true)
{
String message = "";
try {
message = in.readLine();
} catch (IOException e) {
System.out.println("Can't read message from client");
}
if(message.contains("goodbye") == true)
{
d = false;
}
else {
if(threads.get(i) != null)
{
threads.get(i).out.println(username + ": " + message);
}
}
}
}
Just for good measure and a reference here is the overall client class (confusingly labelled ThreadedClient as opposed to ClientThread haha)
ThreadedClient class:
import java.net.*;
import java.io.*;
public class ThreadedClient implements Runnable {
// client socket
private static Socket clientSocket = null;
//I/O streams to and from the server
private static BufferedReader in = null;
private static PrintStream out = null;
// Input stream to read user input
private static BufferedReader inputReader = null;
private boolean open = true;
public ThreadedClient(String host, int port)
{
startConnection(host, port);
}
public void startConnection(String host, int port)
{
//open up the socket
try {
clientSocket = new Socket(host, port);
} catch (UnknownHostException e) {
System.out.println("The host name '" + host + "' isn't known");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Cannot create socket");
}
// connect I/O streams
try {
in = new BufferedReader(new InputStreamReader(new DataInputStream(clientSocket.getInputStream())));
out = new PrintStream(clientSocket.getOutputStream());
inputReader = new BufferedReader(new InputStreamReader(System.in));
} catch (IOException e) {
System.out.println("Problem connecting streams");
}
// process the chat itself
// the thread deals with input coming in
Thread thread = new Thread(this);
thread.start();
// the loop deals with output
while(open == true)
{
String message;
try {
message = inputReader.readLine();
out.println(message);
if(message.contains("goodbye") == true)
{
open = false;
}
} catch (IOException e) {
System.out.println("Problem sending messages");
}
}
// chat is done, so we can close resources
try {
in.close();
inputReader.close();
out.close();
clientSocket.close();
} catch (IOException e) {
System.out.println("Problem closing resources");
}
}
// run method for sending input out. I imagine this will not be necessary in the GUI implemented version, as we can use
// an action listener for the send function, e.g. one that reads a text field into a output stream everytime the user clicks enter
public void run() {
while(open == true)
{
try {
String response = in.readLine();
if(response.contains("goodbye") == true)
{
open = false;
}
System.out.println(response);
} catch (IOException e) {
System.out.println("Problem recieving messages");
}
}
}
public static void main(String[] args)
{
ThreadedClient socket = new ThreadedClient("localhost", 50000);
}
}
I know that this code may not be as advanced as some others I have seen on this forum as well as DreamInCode and others but I was trying to build it from scratch and have been stuck here for what feels like a millennia. Trawling through the internet has not helped :(
Any suggestions and criticisms would be an absolute God send!
Thanks in advance guys.
OK.
You can do like this: Im focus on Console Application
- Define a class call Message:
class Message
{
public String username; // the sender that send this message to u.So you can reply back to this user
public boolean groupMessage; // this message is group message or not
public String message;
}
Define a global variable: ArrayList messages; to hold all incomming messages.
So when you start chat with a client --> create new Thread to read message from him.When you receive a message . You have to put that message to the array list: messages ( you have to remember to sync it. because it will be invoked by many thread)
synchorized(messages){
messages.add(....); // new message here
}
Then , you create a new Thread to show message & can reply back to the sender. In this read you will pop a message from array list messages & show it.
while(isrunning)
{
synchorized(messages){
if(messages.size()<=0) messages.wait(); // when you receive a new message you have to notify
}
synchorized(messages){
Message msg = messages.get(0);
messages.remove(0);
showmessage_to_ouput(msg); // something like this.
String s = read from input // to reply to this message.
Reply(....)// here you can check if this message is group message--> reply to all,..etc
}
}
P/S: That's a idea :) good luck
I can give you a solution , but you have to implement it
We have:
- Server A, Client B & C. B & C already connected to Server via TCP connection
- The first, client B want to chat with C. So B have to send a message by UDP to server
- 2nd, Server will receive a UDP messages from B ==> Server know which ip & port of B that B connected to Server by UDP. Then server send to C a message (TCP) that contains info about UDP ip:port of B .
- 3rd: Client C will receive that message from server via TCP . So C know ip:port that B is listenning .--> If C accept chat with B . C have to send a UDP message to Server to tell server that C accept to talk with B.
- 4th: Server will receive that message via UDP . So Server also know ip:port of C in UDP.
- 5th : The server will transfer UDP ip:port of C to B via TCP (or UDP if you want).
- 6th: Client B will receive it & know udp ip:port of C. So they can start to chat via UDP protocol now.
IT is call UDP/TCP Hole punching. You can research more about it to implement.
P/S: But this method doesnt work with Symetric NAT