Java program one process per user on Microsoft Server - java

I receive bug to fix. Somebody write program which call printing document from other app. Jar with this program is on microsoft server for a few users. Problem is when one of user want print and other too in the same moment. Fox example user1 click print and have print preview, at the same moment user2 do the same action and he don't have print preview, because print prieview of document user2 is displayed on screen user1. I don't know where is bug. Maybe main app call the same instance of jar or the use the same process. Here is my code of method which is called when user click print.
public void openCreatedFile() {
String filePath = "file:///" + findNewlyCreatedFile().replace("\\", "/");
try {
if (xContext != null)
System.out.println("Opening file ...");
xMCF = xContext.getServiceManager();
Object oDesktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);
xCLoader = UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, oDesktop);
com.sun.star.beans.PropertyValue[] szEmptyArgs = new com.sun.star.beans.PropertyValue[0];
xComp = xCLoader.loadComponentFromURL(filePath, "_blank", 0, szEmptyArgs);
System.out.println(filePath);
xDoc = UnoRuntime.queryInterface(com.sun.star.text.XTextDocument.class, xComp);
xContext = null;
} catch (Exception e) {
e.printStackTrace(System.err);
Thread.currentThread();
}
}

You must change your BootstrapSocketConnector. Here is solution:
for(int i = 8100; i<=65535 ; i++){
if(available(i)){
libre.xContext = BootstrapSocketConnector.bootstrap(libre.oooExeFolder, "localhost", i);
System.out.println(i);
break;
}
}
8100 is for example, here you must use your port which is using to connection.
And for example method available() where you check closest available port:
private static boolean available(int port) {
try{
Socket ignored = new Socket("localhost", port);
return false;
} catch (IOException ignored) {
return true;
}
}

Related

Java [Peer-To-Peer]: Runnable stops/blocks unexpectedly

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.

Connect to remote server via telnet and update a file programmatically

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 = "#";

How to create multiple peer-to-peer chats within client-server messaging program

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

cannot get server socket to close

I'm making a simple chat server and just made it so each connection runs on a new thread.
The old version started a single thread for the server, it did a while loop, which would stop when a stop message was sent then close the socket.
The new version loops forever and create a new thread for each new connection. Now I cannot close the socket connection.
If you press a key and the main thread stops, the socket stays open. Thus when I run the program again I need to change the socket number.
code of server
while(true)
{
///////////////////////////////////////////////////
// get a new connection
///////////////////////////////////////////////////
System.out.println("Aceepting connections on port 1030 \r");
try{
// Get New Connection
// wait for ever on accepting new connections
server.setSoTimeout(0);
connection=server.accept();
cConnection thread = new cConnection("thread3", connection);
} catch(IOException ec)
{
System.out.println(ec.getMessage());
}
}
code that starts server
Now each message comes in on a new thread, so I cannot tell it to stop and close the socket.
You need to provide a flag that must be globally accesible, so when some client wants to stop the server then change the variable ans stops the bucle. By example:
class YourServer {
private static boolean execute = true;
public static synchronized void stop() {
execute = false;
}
public void yourMethod() {
while(execute) {
// implement your server here
}
}
}
When a client send the command STOP you must be do
YourServer.stop();
If you want a stop command to stop the server you can call System.exit() to force the program to store or just closing server is likely to be all you need.
Looking into your problem, I understood one thing, that since you are putting
while (true), so your control always gets stuck at connection=server.accept(); listening for a new connection. So in order to stop the sockets you need to first find a way to stop looping in that while loop. Either you can set a Variable, like (int clientsConnected) to check the number of Clients, when that comes to zero stop that while loop. So you can stop your sockets.
Below is my sample code for clients which is doing the same thing for closing the Sockets.
Hopefully this solves your problem.
class GetNamesFromServer implements Runnable
{
private Socket sForName, sForId;
private BufferedReader in, inForName, inForId;
private PrintWriter outForName, outForId;
private static String clientNames;
public GetNamesFromServer(Socket s1, Socket s2)
{
sForName = s1;
sForId = s2;
}
public void run()
{
try
{
outForName = new PrintWriter(sForName.getOutputStream(), true);
outForName.println(Client.clientName);
System.out.println("Send Name : " + Client.clientName);
outForName.flush();
}
catch(IOException e)
{
System.err.println("Error sending Name to the Server.");
}
try
{
inForId = new BufferedReader(new InputStreamReader(sForId.getInputStream()));
Client.clientId = (inForId.readLine()).trim();
System.out.println("Client ID is : " + Client.clientId);
}
catch(IOException e)
{
System.err.println("Error Receiving ID from Server.");
}
try
{
inForName = new BufferedReader(new InputStreamReader(sForName.getInputStream()));
while (true)
{
clientNames = inForName.readLine();
if (clientNames != null && clientNames != "")
{
clientNames = clientNames.substring(1, clientNames.length() - 1);
System.out.println("Names Received : " + clientNames);
String[] names = clientNames.split(", ");
Client.nameClients.clear();
for (String element: names)
Client.nameClients.add(element);
Client.nPane.setText("");
int size = Client.nameClients.size();
System.out.println("Size of list : " + size);
for (int i = 0; i < size; i++)
{
String name = Client.nameClients.get(i);
String colour = Character.toString(name.charAt(0));
name = name.substring(1, name.length()) + "\n";
appendToNamePane(name, ReceiveMessages.getColour(Integer.parseInt(colour)), "Lucida Console");
}
System.out.println("Clients Online : " + Client.nameClients);
}
int index = Client.nameClients.indexOf(Client.clientId + Client.clientName);
**if (index == -1)
{
sForName.close();
break;
}**
}
}
catch(IOException e)
{
System.err.println("Error Receiving Names of Clients from Server");
}
}
NEW EDITION :
You can add a cap to maximum number of clients that can connect, once that reaches your while loop will not go to connection = server.accept(); and hence when they are done chatting (after some time) i.e. totalClients = 0, you can stop your sockets as well, to stop the program.
if (totalClients == 0)
{
socket.close();
serverSocket.close();
}
Regards

Java blocks after calling runtime.exec()

First some code:
Runtime runtime = Runtime.getRuntime();
String args[] = new String[2];
// args[0] = "/bin/bash";
// args[1] = "-c";
// args[2] = "/usr/bin/rpm2cpio "+archiveFile.getCanonicalPath()+" | /bin/cpio -idmv";
args[0] = "/usr/bin/rpm2cpio";
args[1] = archiveFile.getCanonicalPath();
Process rpm2cpioProcess = runtime.exec(args, null, dir);
// System.out.println("started rpm2cpio");
String args2[] = new String[3];
args2[0] = "/bin/cpio";
args2[1] = "-idmu";
args2[2] = "--quiet";
Process cpioProcess = runtime.exec(args2, null, dir);
// System.out.println("started cpio");
InputStream fromRpm2cpio = rpm2cpioProcess.getInputStream();
new ProcessInputStreamer(rpm2cpioProcess.getErrorStream());
OutputStream fromCpio = cpioProcess.getOutputStream();
new PipedStreamer(fromRpm2cpio, fromCpio);
new ProcessInputStreamer(cpioProcess.getErrorStream());
// System.out.println("pipe created");
while(cpioProcess!=null && fromRpm2cpio!=null) {
boolean doSleep = true;
// System.out.println("waking up");
if (cpioProcess!=null) {
try {
if (cpioProcess.exitValue()==0) {
cpioProcess = null;
doSleep = false;
}
} catch(IllegalThreadStateException e) {
}
}
if (rpm2cpioProcess!=null) {
try {
if (rpm2cpioProcess.exitValue()==0) {
rpm2cpioProcess = null;
doSleep = false;
}
} catch(IllegalThreadStateException e) {
}
}
if (doSleep) {
Thread.sleep(30);
}
// System.out.println("still running");
}
I'm trying to extract the content of an rpm archive. This code works fine after multiple modifications. My first attempt was to execute the next code through Java:
/bin/bash -c '/usr/bin/rpm2cpio <archive-file> | /bin/cpio -idmv'
Which worked fine the first time I ran it (you can see it in the code commented above). The second time I ran the code it got blocked since the extracted files already existed. So I thought maybe it has to do with the piping and thus split the call into two separate processes. This didn't help much either. So I then modified the arguments of the /bin/cpio from '-idmv' to '-idmu --quiet' and now it works. Unfortunately the -u option overwrites existing files 'unconditionally' which is not really needed. My question is why does it block with -idmv and why doesn't it block with -idmu ?
It could be waiting on standard input for some inputs. Redirect your standard input and/or output to /dev/null
I'd guess that your ProcessInputStreamer and/or PipedStreamer implement Runnable or extent Thread and you're not running them anywhere.

Categories

Resources