We have a windows application, which was tested on Windows XP, 7, 8, 8.1. Application consists of 2 parts: Bootstrap and main application. Bootstrap assures updates of the main app, and updates main app at a particular point. But users were able to force stop Boostrap process via the Task Manager (Ctrl+Shift+ESC->processes) by killing a process named javaw. In that case main app would not update and elder version would be launched. To avoid such issue we introduced interface of Bootstrap with main application via Socket. Here are the VM parameters of Bootstrap when it starts:
javaw.exe -Xms75M -Xmx90M -Xincgc -jar bootstrap.jar
There is a class SocketServer in the bootstrap:
public class Provider {
ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
public Provider() {
}
public void run() {
try{
providerSocket = new ServerSocket(54345);
connection = providerSocket.accept();
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
do {
try {
message = (String)in.readObject();
if (message.equals("bye")) {
sendMessage("bye");
}
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
} while (!message.equals("bye"));
} catch(IOException ioe) {
ioe.printStackTrace();
} finally {
try {
in.close();
out.close();
providerSocket.close();
} catch(IOException ioef) {
ioef.printStackTrace();
}
}
}
public void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
public void stop() {
if (providerSocket != null && in != null && out != null && !providerSocket.isClosed()) {
try {
in.close();
out.close();
providerSocket.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Main app is being started by Bootstrap via ProcessBuilder like so:
public static void communicate(Process process) {
final BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("Windows-1251")));
final BufferedReader stdErr = new BufferedReader(new InputStreamReader(process.getErrorStream(), Charset.forName("Windows-1251")));
//InputStream
new Thread() {
#Override
public void run() {
String line;
try {
while ((line = stdOut.readLine()) != null) {
debugOut(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
stdOut.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
//ErrorStream
new Thread() {
#Override
public void run() {
String line;
try {
while ((line = stdErr.readLine()) != null) {
debugOut(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
stdErr.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
try {
final Provider provider = new Provider();
ExecutorService pEexec = Executors.newCachedThreadPool();
Future<Void> FPExec = pEexec.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
while (!Thread.currentThread().isInterrupted()) {
provider.run();
}
return null;
}
});
pEexec.shutdown();
process.waitFor();
debugOut("[MainApp] Exit");
provider.stop();
FPExec.cancel(true);
debug("Destroy process");
process.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void startApp() {
try {
ArrayList<String> params = new ArrayList<String>();
...
params.add("-Xms32M");
params.add("-Xmx48M");
params.add("-Xincgc");
params.add("-cp");
params.add(new File(pathToJar, "mainapp.jar").getPath());
params.add("net.craftwork.mainapp.AppStart");
params.add(licCode());
ProcessBuilder procBuild = new ProcessBuilder(params);
debugOut("[MainApp] Start");
Process proc = procBuild.start();
communicate(proc);
} catch (Exception e) {
e.printStackTrace();
}
}
There is a class SocketClient in the main app:
public class Requester {
Socket requestSocket;
ObjectOutputStream out;
ObjectInputStream in;
String message;
static Future<Void> oExec;
Requester() {
}
void run() {
try {
requestSocket = new Socket("localhost", 54345);
out = new ObjectOutputStream(requestSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(requestSocket.getInputStream());
do {
try {
message = (String)in.readObject();
sendMessage("bye");
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
} while (!message.equals("bye"));
} catch(UnknownHostException uhe) {
uhe.printStackTrace();
} catch(IOException ioe) {
ioe.printStackTrace();
oExec.cancel(true);
CommonUtils.debug("Bootstrap not found. Exit.");
System.exit(0);
} finally {
try {
in.close();
out.close();
requestSocket.close();
} catch(IOException ioef) {
ioef.printStackTrace();
}
}
}
void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
public static void main() {
final Requester client = new Requester();
ExecutorService exec = Executors.newCachedThreadPool();
oExec = exec.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
while (!Thread.currentThread().isInterrupted()) {
client.run();
Thread.sleep(1000);
}
return null;
}
});
exec.shutdown();
}
}
Socket Client is called when main application starts
public class AppStart {
public static void main(final String[] args) {
Requester.main();
EventQueue.invokeLater(new Runnable() {
public void run() {
...
}
});
}
}
This is all to it I do believe. Whole setup worked perfectly fine, even on slower computers. Problem is that after introduction of Socket interface we had major complaints from some users, reporting crashes. Took us some time to figure out the issue, but here is what we found: computers with Intel processors are perfectly fine, only ones with AMD processors crash. Crash normally happens within 3 to 15 minutes from the start of Bootstrap. When crash occurs resources of the computer are not fully used, processor workload is about 20-50% and RAM is quite free as well. When crash occurs user is only able to reset computer using hardware reset or power button, nothing else responds. All users have latest JAVA 1.7.0_51. Whether system is 32 or 64 bit does both crash (or not crash if it is Intel based). Please share your thoughts. May be someone had identical issues and could help me to figure this out.
Related
I have to create a simple rotating proxy application where 100 requests get evenly distributed to 10 devices. I've got the following structure:
WebServer with a Java-SocketServer running. All Android devices are connected to this Socket-Server to be able to know which devices are currently online and for determining which device should be used for the next request.
10 Android devices in different networks. They are connected to the Socket Server and are waiting for requests that should be forwarded to the remote address and then sent back to the SocketServer.
In easy words: I basically have to create an application similar like Honeygain, Peer2Profit or IPRoyal Pawns so that I can later do requests like this:
//Use "-x" to set Proxy-IP and Proxy-Port
curl -x ANDROID_DEVICE_IP:PORT -L https://www.google.com
I managed to have an always running proxy service in an Android application. It basically looks like this and just forwards HTTP-Requests from Port 1440 to the desired remote address and then sends the response back to the original client. The Proxy basically works fine.
public class ProxyServerThread extends Thread {
public static void main(String[] args) {
(new ProxyServerThread()).run();
}
public ProxyServerThread() {
super("Server Thread");
}
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(1440)) {
Socket socket;
try {
while ((socket = serverSocket.accept()) != null) {
(new Handler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
return;
}
}
public static class Handler extends Thread {
public static final Pattern CONNECT_PATTERN = Pattern.compile("CONNECT (.+):(.+) HTTP/(1\\.[01])", Pattern.CASE_INSENSITIVE);
private final Socket clientSocket;
private boolean previousWasR = false;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
String request = readLine(clientSocket);
System.out.println(request);
Matcher matcher = CONNECT_PATTERN.matcher(request);
if (matcher.matches()) {
String header;
do {
header = readLine(clientSocket);
} while (!"".equals(header));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(clientSocket.getOutputStream(), "ISO-8859-1");
final Socket forwardSocket;
try {
forwardSocket = new Socket(matcher.group(1), Integer.parseInt(matcher.group(2)));
System.out.println(forwardSocket);
} catch (IOException | NumberFormatException e) {
e.printStackTrace(); // TODO: implement catch
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 502 Bad Gateway\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
return;
}
try {
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 200 Connection established\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
Thread remoteToClient = new Thread() {
#Override
public void run() {
forwardData(forwardSocket, clientSocket);
}
};
remoteToClient.start();
try {
if (previousWasR) {
int read = clientSocket.getInputStream().read();
if (read != -1) {
if (read != '\n') {
forwardSocket.getOutputStream().write(read);
}
forwardData(clientSocket, forwardSocket);
} else {
if (!forwardSocket.isOutputShutdown()) {
forwardSocket.shutdownOutput();
}
if (!clientSocket.isInputShutdown()) {
clientSocket.shutdownInput();
}
}
} else {
forwardData(clientSocket, forwardSocket);
}
} finally {
try {
remoteToClient.join();
} catch (InterruptedException e) {
e.printStackTrace(); // TODO: implement catch
}
}
} finally {
forwardSocket.close();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
}
private static void forwardData(Socket inputSocket, Socket outputSocket) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[4096];
int read;
do {
read = inputStream.read(buffer);
if (read > 0) {
outputStream.write(buffer, 0, read);
if (inputStream.available() < 1) {
outputStream.flush();
}
}
} while (read >= 0);
} finally {
if (!outputSocket.isOutputShutdown()) {
outputSocket.shutdownOutput();
}
}
} finally {
if (!inputSocket.isInputShutdown()) {
inputSocket.shutdownInput();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
private String readLine(Socket socket) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int next;
readerLoop:
while ((next = socket.getInputStream().read()) != -1) {
if (previousWasR && next == '\n') {
previousWasR = false;
continue;
}
previousWasR = false;
switch (next) {
case '\r':
previousWasR = true;
break readerLoop;
case '\n':
break readerLoop;
default:
byteArrayOutputStream.write(next);
break;
}
}
return byteArrayOutputStream.toString("ISO-8859-1");
}
}
}
Here comes the Problem:
Everything works fine but only on the local network. I cannot manage to get this to work without port forwarding. Since all devices are on their mobile cellular data I need a way to be able to connect to the device anyway.
How do the mentioned apps manage to connect to the devices?
So my problem is I have a client with a Runnable that readobjects in background from the socket. In the server i send multiple times objects like notifications updates etc by writeUnshared, but the client is only receiving them when I send a request back to server by writeUnshared.
\ClientThread.java\
public class ThreadClientInFromServer implements Runnable {
Socket socket;
ClientData clientData;
public ThreadClientInFromServer(Socket socket, ClientData clientData) {
this.socket = socket;
this.clientData = clientData;
}
#Override
public void run() {
ObjectInputStream in;
ObjectOutputStream out;
out = clientData.getOut();
in = clientData.getIn();
while (!socket.isClosed()) {
try {
Object object = in.readObject();
clientData.updateData(object);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
SendRequestClient.java Only when i send this request it refresh and come the updates,notifications,etc
public void sendRequest(Request request) {
try {
out.writeObject(request);
out.flush();
out.reset();
} catch (IOException e) {
System.out.println("[ERROR] ON SEND REQUEST!");
return;
}
}
On Server (KEEPALIVETCP.java) for example, he doesnt receive.
public class KeepAliveTCP implements Runnable {
ServerModel serverModel;
public KeepAliveTCP(ServerModel serverModel) {
this.serverModel = serverModel;
}
#Override
public void run() {
Request request = new Request(null, Constants.ACK);
while (!serverModel.getSocket().isClosed()) {
try {
for (SocketModel clients : serverModel.getModelClientes()) {
if (clients.getNome() != null) {
clients.getOut().writeUnshared(request);
clients.getOut().flush();
}
}
sleep(5000);
watchWhoFails();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks in Advance!!!
EDIT : So I was trying to find a solution and come up with my cliente blocking the thread(ThreadClientInFromServer) when he uses scanner.next() on the menus(that user uses to browse on the application). So I dont really know how to solve this problem, if you guys know some solution for this!
Thanks.
Recently I added "adb devices" in the nano ./bash_profile so that I can run it from any directory.
I used one java application to run
public static void main(String [] args) {
executeCmd("adb devices");
}
private static void executeCmd(String string) {
InputStream pipedOut = null;
try {
Process aProcess = Runtime.getRuntime().exec(string);
// These two thread shall stop by themself when the process end
Thread pipeThread = new Thread(new StreamGobber(aProcess.getInputStream()));
Thread errorThread = new Thread(new StreamGobber(aProcess.getErrorStream()));
pipeThread.start();
errorThread.start();
aProcess.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
class StreamGobber implements Runnable {
private InputStream Pipe;
public StreamGobber(InputStream pipe) {
if(pipe == null) {
throw new NullPointerException("bad pipe");
}
Pipe = pipe;
}
public void run() {
try {
byte buffer[] = new byte[2048];
int read = Pipe.read(buffer);
while(read >= 0) {
System.out.write(buffer, 0, read);
read = Pipe.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(Pipe != null) {
try {
Pipe.close();
} catch (IOException e) {
}
}
}
when I run any other commands such as "ls" it's working fine!!
I'm using mac ..
thanks :)
Maybe global path problem on mac. You can try run with absolute adb program path as command.
Here is the scenario:
1. I have a GSM modem which is connected to my computer, It's working I can read and send SMS via the built-in program.
2. The port assign to my gsm modem is COM11 . I saw it from DeviceManager -> modems -> myModem-> Advance -> AdvancePortSettings.
3. I write the Java code to read incomming message.
The code is as follows:
public class PScanner implements SerialPortEventListener, Runnable {
CommPortIdentifier pid = null;
SerialPort sp;
BufferedReader input;
OutputStream output;
public PScanner() {
try {
Enumeration e = CommPortIdentifier.getPortIdentifiers();
while (e.hasMoreElements()) {
CommPortIdentifier cpi = (CommPortIdentifier) e.nextElement();
if (cpi.getName().equals("COM11")) {
pid = cpi;
break;
}
}
sp = (SerialPort) pid.open(getClass().getName(), 2000);
sp.setSerialPortParams(115200, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
InputStream is = sp.getInputStream();
input = new BufferedReader(new InputStreamReader(is));
output = sp.getOutputStream();
sp.addEventListener(this);
sp.notifyOnDataAvailable(true);
new Thread(this).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public synchronized void serialEvent(SerialPortEvent oEvent) {
System.out.println("serialEvent CallBack");
}
public synchronized void close() {
if (sp != null) {
sp.removeEventListener();
sp.close();
}
}
#Override
public void run() {
try {
Thread.sleep(20000);
} catch (InterruptedException ex) {
Logger.getLogger(PScanner.class.getName()).log(Level.SEVERE, null, ex);
} finally {
System.out.println("done");
}
}
}
When I send an SMS on the GSM modem, I am not getting in serialEvent() call back method.
Do anyone know what is going on? I am not getting any error or exceptions.
This isn't a definitive answer, but your code has made several question marks appear above my head.
To answer why you're not getting anything in the method listening on the SerialEvent, it might be that you are adding the listener after the event has happened.
Try moving sp.addEventListener(this); further up, just after 'pid.open'.
However think a bit about what the thread is doing. All your code is in the constructor of your class, then at the end of the constructor, after everything has happened, you call thread.start(), so none of your code is running in a separate thread. Your run method actually does nothing except send the thread to sleep after everything has happened.
Move all your code from the constructor to the run() method if you want it to run in a separate thread.
The following code , is to send and read message using a GSM module, this may help you
import java.sql.*;
import java.io.*;
import java.util.*;
import java.text.*;
import gnu.io.*;
public class SerialComm implements SerialPortEventListener
{
int result=0;
static CommPortIdentifier portId=null;
Enumeration portList=null;
static InputStream inputStream=null;
static OutputStream out=null;
static SerialPort serialPort=null;
static int srate=9600;//B-Rate
String data=null;
int i=0;
String number="";
int status=0;
public String recvdData="aa";
String pswd="";
String actualpswd="";
public static void main(String args[])
{
SerialComm obj=new SerialComm();
}
public SerialComm()
{
try
{
if(this.detectPort())
{
if(this.initPort())
{
//Thread.sleep(2000);
// sendMessage();
}
}
}
catch(Exception e)
{
System.out.println("Error in SerialComm()-->"+e);
}
}
public boolean detectPort()
{
boolean portFound = false;
//String defaultPort = "/dev/ttyUSB0";
String defaultPort = "COM1";
try
{
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements())
{
CommPortIdentifier portID = (CommPortIdentifier) portList.nextElement();
if (portID.getPortType() == CommPortIdentifier.PORT_SERIAL)
{
if (portID.getName().equals(defaultPort))
{
this.portId=portID;
System.out.println("Found port: "+portId.getName());
portFound = true;
break;
}
}
}
if (!portFound)
{
System.out.println("port " + defaultPort + " not found.");
}
}
catch(Exception e)
{
portFound = false;
}
return portFound;
}
public boolean initPort()
{
try
{
serialPort = (SerialPort) portId.open("SerialCommApp", 2000);
}
catch (PortInUseException e)
{
System.out.println("Port in use-->"+e);
}
try
{
inputStream = serialPort.getInputStream();
out=serialPort.getOutputStream();
}
catch (IOException e)
{
System.out.println("IO Error-->"+e);
}
try
{
serialPort.addEventListener(this);
}
catch (TooManyListenersException e)
{
System.out.println("Too many LIstener-->"+e);
}
serialPort.notifyOnDataAvailable(true);
try
{
serialPort.setSerialPortParams(srate, SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT);
}
catch (UnsupportedCommOperationException e)
{
System.out.println("Error while setting parameters-->"+e);
}
System.out.println("Port Initialized....");
return true;
}
public synchronized void serialEvent(SerialPortEvent event)
{
switch (event.getEventType())
{
case SerialPortEvent.DATA_AVAILABLE:
System.out.println("DATA_AVAILABLE");
byte[] readBuffer = new byte[1024];
int numBytes=1024;
data="";
try
{
Thread.sleep(100);
while (inputStream.available() > 0)
{
numBytes = inputStream.read(readBuffer);//count of reading data
data=data+new String(readBuffer,0,numBytes);
data=data.trim();
this.recvdData+=data;
}
System.out.println("data=========="+this.recvdData);
}
catch (Exception e)
{
System.out.println("Exception in serial event-->"+e);
}
break;//break from switch case 1:
}//end of switch
}
Method to read Message
public void sendMessage(String num, String msg) {
try{
System.out.println("Sending Message");
this.recvdData="";
String dq=String.valueOf((char)34);
String mysms="AT+CMGS="+dq+num+dq;
out.write(mysms.getBytes());
out.write(13);
Thread.sleep(500);
mysms=msg;
out.write(mysms.getBytes());
out.write(26);
out.write(13);
Thread.sleep(500);
if(this.recvdData.contains("OK"))
{
return;
}else if(this.recvdData.contains(">")){
out.write(26);
out.write(13);
sendMessage(num,msg);
}else{
sendMessage(num,msg);
}
return;
}catch(Exception e){
System.out.println(e);
}
}
Check these code, i got the output by using this code,
I have a a GPS receptor. I create a class to retrieve all the GPS data on my Eclipse Console.
(This is the code of makia42)
public class COM implements Runnable{
static Thread myThread=null;
static BufferedReader br;
static BufferedWriter wr;
static InputStreamReader isr;
static OutputStreamWriter osw;
static java.io.RandomAccessFile port;
public COM(){ /**Constructeur*/
myThread=new Thread(this);
}
public void start(){
try {
port=new java.io.RandomAccessFile("COM3","rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
}
catch (Exception e) {
System.out.println("start "+e.toString());
}
myThread.start();
}
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
public static void main(String[] args) {
COM temp= new COM();
temp.start();
}
}
I have another class which is a frame containing a button and a JTextArea. This class is in communication with my first class COM.
When i click the button, COM is starting and show me the data in my Eclipse Console.
But now, I'd like to show it on my JTextArea.
How can I do it ?
Best regards,
Tofuw
Take a moment to read about this pattern.
Make the Thread a Subject. Before starting register the instance of the class that contains the JTextArea as the Observer with the instance of the Thread. At the run() instead of printing on the console, use the notify(String);
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
Change to
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
notifyObservers(st); //Pass the data to the observers.
}
}
EDIT:
I suppose you can rewrite the Thread to a simple class. It will render the program unresponsive while it reads, that's why you have a Thread. I suppose you can implement a cleaner way using Future<String>
public class GpsReader {
public class GenericGPSException extends Exception {
public GenericGPSException(String message, Throwable cause) {
super(message, cause);
}
}
public static void main(String[] args) {
// Example of usage
GpsReader gpsReader = new GpsReader();
String messageFromDevice;
try {
// Try read it
messageFromDevice = gpsReader.getCoordinate();
} catch (GenericGPSException e) {
// Error, what does it says?
messageFromDevice = e.getMessage();
}
JTextArea mockArea = new JTextArea();
// Show to user anything that comes to it.
mockArea.setText(messageFromDevice);
}
private boolean isReady;
private RandomAccessFile port;
public GpsReader() {
}
public String getCoordinate() throws GenericGPSException {
if (!isReady) {
try {
port = new RandomAccessFile("COM3", "rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
isReady = true;
} catch (FileNotFoundException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
} catch (IOException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
}
}
try {
return port.readLine();
} catch (IOException e) {
throw new GenericGPSException("Error at reading the Device ", e);
}
}
}