How can I break an infinite loop at runtime? - java

Say that I have:
b = true;
while(b){}
Is there any way to continue on after this point? Like some way to modify the value of b without stopping and re running the program?
I want to do this as a simple method to pause the program for an unspecified amount of time, that changes all the time.

You can read the value of b from a data source that is modifiable by the user during runtime.
This can be anything from a database, a network socket, or simply a file.
In this case I would recommend a socket. Below is a very rough, but working, example.
Once you start the program in Eclipse, you need to open a terminal window and telnet localhost 10008.
The accepted commands via the socket are:
<numeric value> = pause the app for that amount of milliseconds
BYE = close the socket
STOP = completely stop the app
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class RuntimePause extends Thread {
protected static boolean appRunning = true;
protected Socket clientSocket;
private long pause = 0;
public static void main(String[] args) throws IOException {
RuntimePause app = new RuntimePause();
app.start();
while (true) {
app.listen();
}
}
public void run() {
while (appRunning) {
System.out.println("App running...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
if (pause > 0) {
System.out.println("App pausing for " + pause + " ms");
try {
Thread.sleep(pause);
} catch (InterruptedException e) {
}
pause = 0;
}
}
}
public void listen() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(10008);
System.out.println("Connection Socket Created");
try {
while (appRunning) {
System.out.println("Waiting for Connection");
new NetworkSocket(serverSocket.accept());
}
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
} catch (IOException e) {
System.err.println("Could not listen on port: 10008.");
System.exit(1);
} finally {
try {
serverSocket.close();
} catch (IOException e) {
System.err.println("Could not close port: 10008.");
System.exit(1);
}
}
}
public class NetworkSocket extends Thread {
public NetworkSocket(Socket clientSoc) {
clientSocket = clientSoc;
start();
}
public void run() {
{
System.out.println("New Communication Thread Started");
try {
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Received: " + inputLine);
// Client sent a pause command
try {
long pauseCommand = Long.parseLong(inputLine);
pause = pauseCommand;
out.println("OK, pausing for " + inputLine + " ms");
} catch (NumberFormatException e) {
//
}
// Client wishes to terminate connection to socket
if (inputLine.equals("BYE")) {
out.println("OK, bye!");
break;
}
// Client orders the app to stop
if (inputLine.equals("STOP")) {
out.println("OK, stopping!");
System.exit(1);
}
}
out.close();
in.close();
clientSocket.close();
} catch (IOException e) {
System.err.println("Problem with Communication Server");
System.exit(1);
}
}
}
}
}
By the way, this code is not production ready. It simply serves as a example of how you can approach the problem. You want to ensure that the variables are accessed in a thread-safe way.

BOOL b;
- (void)viewDidLoad {
[super viewDidLoad];
//Create a button
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
//Which is black
button.backgroundColor = [UIColor blackColor];
//Add it to the view
[self.view addSubview:button];
//When you press the button, do stopPrintingB method
[button addTarget:self action:#selector(stopPrintingB) forControlEvents:UIControlEventTouchUpInside];
b = true;
/*
* This is a GCD means not in the main thread
* If you make while(b) in the main thread
* the program will not do stopPrintingB method until the main thread is free
*/
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
while (b) {
NSLog(#"printing b");
}
});
}
//make b false and stopPrintingB
- (void)stopPrintingB
{
b = false;
}

If you run your program in debug mode you can inject code that will break the loop. In the example posted just change:
b = true;
while(b){}
to:
b = true;
while(b){b=false;}
Then save the file and the loop will be broken.

Related

DataInputStream not Receiving Data After Flushing DataOutputStream

So, I'm fairly new to sockets and data streams... And I am absolutely baffled by this issue I'm having. I've searched for hours trying to find a solution, assuming that other people might have had the same issue I'm having, but I've found absolutely nothing helpful so far.
I'm writing a very simple multithreaded server/client program that is supposed to open a serverSocket, and accept connections from clients, storing them in a simple arraylist (I'll change the storage process once I actually get messages to send), and then a message handler thread parses the list, and checks if a user has written to the server. If the user has written something, the program then displays the resulting message to the console. My program successfully writes to the server socket through the DataOutputStream, but when I attempt to read from the corresponding DataInputStream on the server side, it says the stream is empty, and my program will continue to loop. I've checked that the DataOutputStream receives the data through DataOutputStream.size(), and that the DataInputStream I am attempting to read data from corresponds to the correct DataOutputStream I mentioned before.
User Code:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
public class User {
private String hashID;
private Socket connection;
private static int hashVal = 0;
DataInputStream consoleInputStream;
String consoleInput = "";
public User(Socket conn) throws SocketException {
hashID = hashUserKey();
connection = conn;
connection.setSoTimeout(1500);
consoleInputStream = new DataInputStream(System.in);
}
private static String hashUserKey() { //placeholder for now
hashVal++;
return("Guest" + hashVal);
}
public Socket getSocket() {
return this.connection;
}
public String getID() {
return this.hashID;
}
public boolean disconnect() {
try {
consoleInputStream.close();
connection.close();
return true;
} catch (IOException e) {
System.err.println(hashID + " was unable to successfully disconnect");
return false;
}
}
public void startConnection() {
new Thread() {
#Override
public void run() {
while(!connection.isClosed()) {
try {
consoleInput = consoleInputStream.readLine();
if(consoleInput != null || consoleInput != "") {
writeToServer(consoleInput);
}
} catch (IOException e) {
System.err.println("Was not able to read console input");
}
}
System.out.println("You were disconnected, have a nice day!");
return;
}
}.start();
}
private boolean writeToServer(String toWrite) {
try {
String msg = hashID + ">>>: " + toWrite;
DataOutputStream outStream = new DataOutputStream(connection.getOutputStream());
outStream.writeUTF(toWrite + "\r\n");
outStream.flush();
consoleInput = "";
System.out.println(msg + "\t was written to " + connection.getInetAddress() + ":" + connection.getPort());
return true;
} catch (IOException e) {
System.err.println(hashID + " was unable to write to server");
return false;
}
}
#Override
public boolean equals(Object o) {
User t = (User) o;
if(t.hashID == this.hashID) {
return true;
}
return false;
}
}
Server Code:
import java.net.*;
import java.io.*;
import java.util.*;
public class TestServer {
private static ServerSocket server;
private static TestLogger logger;
private static Thread serverHandlerThread;
private static Thread messageHandlerThread;
private static ArrayList<User> users;
private static volatile boolean hasBeenStopped = false;
public static boolean startServer(int port) {
logger = new TestLogger();
logger.log("Attempting to create default shutdown behavior for server");
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
if(!hasBeenStopped) {
logger.warn("Server was shut down without running stopServer(), running by default");
stopServer();
}
}
}
);
logger.log("Shutdown behaivor created. Now attempting to set up user database"/*TODO create a real database*/);
users = new ArrayList<User>();
logger.log("Attempting to start server");
try {
server = new ServerSocket(port);
logger.log("Server successfully started at " + server.getInetAddress() + ":" + server.getLocalPort() +", now attempting to start user connection handler");
serverHandlerThread = new Thread() {
#Override
public void run() {
this.setName("serverHandlerThread");
while(!server.isClosed()) {
try {
Socket temp = server.accept();
logger.log("Connection accepted from " + temp.getInetAddress());
System.out.println("Connection accepted from " + temp.getInetAddress());
startUserConnection(new User(temp));
} catch (SocketException e) {
logger.warn("Server was closed while in accept phase");
} catch (IOException e) {
e.printStackTrace();
}
}
logger.log(this.getName() + " was stopped, server socket was closed successfully");
return;
}
};
serverHandlerThread.start();
logger.log("Server thread successfully started, listening for connections on: " + server.getInetAddress().toString() + ":" + port);
logger.log("Attempting to start message handler thread to read user inputs");
messageHandlerThread = new Thread() {
#Override
public void run() {
this.setName("messageHandlerThread");
while(!server.isClosed()) {
if(users.isEmpty()) {
continue;
}
for(int i = 0; i < users.size(); i++) {
User temp = users.get(i);
try {
System.out.println(new DataInputStream(temp.getSocket().getInputStream()).readUTF());
} catch (IOException e) {
System.err.println("Nothing to read from client: " + temp.getID());
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
messageHandlerThread.start();
return true;
} catch (IOException e) {
logger.error("Could not bind server socket to port.");
return false;
}
}
public static boolean stopServer() {
logger.log("Started shut down process");
if(serverHandlerThread == null || !serverHandlerThread.isAlive()) {
logger.warn("Thread has not been started yet or has already been killed");
return false;
}
else {
stopAllUserConnections();
try {
server.close();
hasBeenStopped = true;
while(serverHandlerThread.isAlive()) {
}
logger.log("Server was successfully shut down");
return true;
} catch (IOException e) {
logger.error("Could not close server socket");
return false;
}
}
}
private static void startUserConnection(User user) {
logger.log("Connected new user from " + user.getSocket().getInetAddress());
users.add(user);
System.out.println(user.getID() + " was added to list");
user.startConnection();
}
private static boolean stopUserConnection(User user) {
logger.log("Attempting to disconnect user, address: " + user.getSocket().getInetAddress());
for(User u : users) {
if(u.equals(user)) {
u.disconnect();
return true;
}
}
logger.warn("Could not find user with address: " + user.getSocket().getInetAddress());
return false;
}
private static boolean stopAllUserConnections() {
logger.log("Attempting to disconnect all users from the server");
if(users.isEmpty()) {
logger.warn("No users available to disconnect");
return false;
}
for(User u : users) {
u.disconnect();
}
users.clear();
return true;
}
public static void main(String args[]) {
startServer(*the_port*);
Client c = new Client();
c.connect("0.0.0.0", *the_port*);
}
}
Client Code:
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public boolean connect(String serverName, int port) {
try {
System.out.println("Attempting to connect");
Socket sock = new Socket(serverName, port);
System.out.println("Connected");
return true;
} catch (UnknownHostException e) {
System.err.println("Could not resolve " + serverName + ":" + port);
}
catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
So as I said above, this works fine up until I attempt to read the data written to the server. No matter what I do, the server's call to readUTF() on the socket always throws an IOException and checking the bytes ready to read by using DataInputStream.available() returns 0 as well. My sample output from my most recent run is as follows:
Attempting to connect
Connected
Connection accepted from *the_address*
Guest1 was added to list
Nothing to read from client: Guest1
Nothing to read from client: Guest1
Nothing to read from client: Guest1
test
Guest1>>>: test was written to *the_address:another_port*
Nothing to read from client: Guest1
Nothing to read from client: Guest1
Nothing to read from client: Guest1
I know my code may be terribly optimized, and I'll work on fixing that later, but right now, all I want to know is why my DataInputStream is empty after flushing the corresponding DataOutputStream, and how I can successfully send UTF data between them.

Server did not read message from last client

I need to simulate a distributed system.
There is a controller and n worker computers.
The controller tells the computers when to start, and the computers will start connecting to other computers using sockets. The controller is connecting to the computers using threads. The computer will connect to other computers using threads as well.
Once they are connected to each other, they will send events to each other until they have generated x events. Once they reach x events, the computer will send a "Finish" message to the controller saying that it's done generating events, but will continue reading events from other computers.
My issue: The computers have successfully sent the Finish message to controller, except the last computer in the system. According to the logs, the last computer did send the Finish message to the controller, but the controller did not receive it. The other computers successfully sent the finish message to the controller.
If you need more information, I would be glad to provide. I have been working on this for hours and have no clue.
Computer.java
package timetableexchange;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Vector;
public class Computer {
// Constant system capacity
static final int MAX_SYSTEMS = 4;
// Computer's time-stamp vector
static Vector<Integer> timestamp = new Vector<Integer>();
// Computer's ID
static int identifier;
// Computer's Event Count
static int eventCount = 0;
// Computer's isAlive check
static boolean isAlive = true;
// Socket to Controller
Socket socketToController;
PrintWriter outputToController;
BufferedReader inputFromController;
String textFromController;
// Server Socket
ServerSocket serverSocket;
// Input and Output Clients
static ArrayList<ClientSocket> outputClients = new ArrayList<ClientSocket>();
static ArrayList<ClientConnection> inputClients = new ArrayList<ClientConnection>();
// Log
Log log;
public static void main(String[] args) throws IOException {
new Computer("127.0.0.1", 8000);
}
public Computer(String hostname, int port) throws IOException {
// Initialize time-stamp
for (int i = 0; i < MAX_SYSTEMS; ++i) {
timestamp.add(0);
}
// Connect to Controller
try {
socketToController = new Socket(hostname, port);
inputFromController = new BufferedReader(new InputStreamReader(socketToController.getInputStream()));
outputToController = new PrintWriter(socketToController.getOutputStream(), true);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
// Get Computer ID from Controller
while (true) {
try {
if (inputFromController.ready()) {
textFromController = inputFromController.readLine();
identifier = Integer.parseInt(textFromController);
break;
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
log = new Log("client" + identifier + ".txt");
// Read start message
while (true) {
try {
if (inputFromController.ready()) {
textFromController = inputFromController.readLine();
if (textFromController.equals("Start")) {
log.write("Computer is starting!");
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
// Instantiate server socket
int socketPort = port + identifier + 1;
// System.out.println(socketPort);
serverSocket = new ServerSocket(socketPort);
log.write("Server Socket Instantiated");
// Instantiate sockets for other server sockets (computers) to send
for (int i = 0; i < MAX_SYSTEMS; ++i) {
if (i != identifier) {
Socket acceptedSocket = new Socket(hostname, port + i + 1);
ClientSocket socketToComputer = new ClientSocket (acceptedSocket);
outputClients.add(socketToComputer);
}
}
log.write("Client Sockets Instantiated\n");
// Accept sockets from server socket and add them into a list
for (int i = 0; i < MAX_SYSTEMS - 1; ++i) {
ClientConnection computerConn = new ClientConnection(serverSocket.accept());
computerConn.start();
inputClients.add(computerConn);
}
log.write("Server connected to clients");
Random rand = new Random();
// Generating events
int temp;
while (eventCount < 50) {
log.write("Generating Event");
int choice = rand.nextInt(5);
if (choice == 0) {
temp = timestamp.get(identifier);
++temp;
timestamp.set(identifier, temp);
} else {
int randC = rand.nextInt(outputClients.size());
ClientSocket cc = outputClients.get(randC);
cc.out.writeObject(new Event(identifier, timestamp));
}
log.write(timestamp.toString());
log.write("Done Generating Event");
eventCount++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.write("Finished writing. Continue reading...");
/**
* ========THE ISSUE IS BELOW.===============
*/
synchronized (outputToController) {
outputToController.println("Finish");
outputToController.flush();
}
log.write("Sent Finish Message " + identifier);
// Wait for Tear Down Message
while (true) {
try {
if (inputFromController.ready()) {
textFromController = inputFromController.readLine();
if (textFromController.equals("Tear Down")) {
log.write("Tearing down....");
isAlive = false;
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.write("Computer shutting off....");
}
// client socket class (organizing)
public class ClientSocket {
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
public ClientSocket(Socket s) {
try {
this.socket = s;
this.out = new ObjectOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
log.write("Client Socket Created");
}
}
// send event thread
public class ClientConnection extends Thread {
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
Random rand = new Random();
public ClientConnection(Socket s) {
this.socket = s;
try {
out = new ObjectOutputStream (socket.getOutputStream());
in = new ObjectInputStream (socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run () {
while (isAlive) {
log.write("Reading events");
try {
Event event = (Event) in.readObject();
executeEvent(event.getFromID(), event.getTimestamp());
} catch (ClassNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(timestamp);
}
log.write("Finished Reading");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// execute the event
private void executeEvent(int from, Vector<Integer> x) {
int temp;
synchronized (timestamp) {
for (int i = 0; i < timestamp.size(); ++i) {
if (x.get(i) > timestamp.get(i)) {
timestamp.set(i, x.get(i));
}
}
temp = timestamp.get(from);
++temp;
timestamp.set(from, temp);
}
}
}
}
Controller.java
package timetableexchange;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Controller {
// Mutex Lock
public final static Object lock = new Object();
// Constant system capacity
static final int MAX_SYSTEMS = 4;
// Server connection threads to computers
static ArrayList<ServerConnection> conns = new ArrayList<ServerConnection>();
// Finished computers
static int finishedCount = 0;
// Server Socket
ServerSocket ss;
// Log Instance
Log log;
public static void main(String[] args) throws IOException {
new Controller(8000);
}
public Controller(int port) {
// Instantiate Log
log = new Log("server.txt");
// Instantiate Server Socket and Listen for Incoming Sockets
try {
ss = new ServerSocket(port);
log.write("Listening...");
// Accept computers until capacity
for (int i = 0; i < MAX_SYSTEMS; i++) {
Socket s = ss.accept();
log.write("Socket connected");
// Add to list
ServerConnection conn = new ServerConnection(i, s);
conns.add(conn);
conn.start();
}
// Notify all waiting threads to start
synchronized (lock) {
try {
Thread.sleep(1000);
lock.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class ServerConnection extends Thread {
// Client Socket
Socket socket;
// Output stream
PrintWriter out;
// Input stream
BufferedReader in;
// ID for connected computer
int identifier;
public ServerConnection(int i, Socket s) {
// Instantiate properties
this.identifier = i;
this.socket = s;
try {
this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.out = new PrintWriter(socket.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
log.write("Controller is connected to computer#" + identifier);
// Send ID to computer
out.println(identifier);
// Wait until notified
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Send Start Message to All Computers
sendAll("Start");
waitForFinish();
log.write("Computer#" + identifier + " is waiting for tear down.");
// If all computers sent the Finish message, send a Tear Down
while (true) {
if (finishedCount == conns.size()) {
log.write("Sending tear down to all computers");
sendAll("Tear Down");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* ==== RECEIVE FINISH MESSAGE FROM COMPUTERS ======
*/
private void waitForFinish() {
String clientInput;
while (true) {
try {
if (in.ready()) {
clientInput = in.readLine();
log.write(clientInput);
if (clientInput.equals("Finish")) {
finishedCount += 1;
log.write("Computer " + identifier + " is finished");
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Send all "text" to all computers in the thread pool
private void sendAll(String text) {
for (int i = 0; i < conns.size(); ++i) {
ServerConnection conn = conns.get(i);
conn.out.println(text);
}
}
}
}
Controller Log: (notice that the log does not say computer 3 is finished)
Listening... (Listening for Computer)
Socket connected
Controller is connected to computer#0
Socket connected
Controller is connected to computer#1
Socket connected
Controller is connected to computer#2
Socket connected
Controller is connected to computer#3
Computer 2 is finished
Computer 1 is finished
Computer#2 is waiting for tear down.
Computer 0 is finished
Computer#1 is waiting for tear down.
Computer#0 is waiting for tear down.
Computer #0 Log: (I cut down the log because there was a lot of reading and writing event log statements)
Computer is starting!
Server Socket Instantiated
Client Socket Created
Client Socket Created
Client Socket Created
Client Sockets Instantiated
Server connected to clients
// A bunch of reading and writing events
Finished writing. Continue reading...
Sent Finish Message 0
Computer #1 Log:
Computer is starting!
Server Socket Instantiated
Client Socket Created
Client Socket Created
Client Socket Created
Client Sockets Instantiated
Server connected to clients
Finished writing. Continue reading...
Sent Finish Message 1
Computer #2
Computer is starting!
Server Socket Instantiated
Client Socket Created
Client Socket Created
Client Socket Created
Client Sockets Instantiated
Reading events
Server connected to clients
Finished writing. Continue reading...
Sent Finish Message 2
Computer #3: According to the log, this sent the finished message to controller
Computer is starting!
Server Socket Instantiated
Client Socket Created
Client Socket Created
Client Socket Created
Client Sockets Instantiated
Reading events
Server connected to clients
Finished writing. Continue reading...
Sent Finish Message 3

Wait Until Condition become true

I got three classes in, which are TCPClient.java, TCPProtocol.java, TCPServer.java .
*Update, i paste my full TCPServer.java as well
first, user will input the text in TCPProtocol GUI Window (by using JTextarea), and click button "Send". TCPClient will get the input from TCPProtocol if user click "send", and last will send to TCPServer. So the problem is, my TCPClient never get the input from TCPProtocol.
TCPServer.java
import java.net.*;
import java.io.*;
public class TCPServer {
public static void main(String[] args) throws IOException {
//TCP component
ServerSocket serverSocket = null;
Socket clientSocket = null;
int port = 8081;
TCPProtocol nis = new TCPProtocol();//create an object to call method in protocol class
try {
serverSocket = new ServerSocket(port);
System.out.println("Waiting for connection...");
System.out.println();
} catch (IOException e) {
System.out.println(e.toString() + " :Could not listen on port: " + port);
System.exit(1);
}
try {
clientSocket = serverSocket.accept();
System.out.println("TCP Session established.");
nis.frame.setVisible(true);
nis.frame.setAlwaysOnTop(true);
System.out.println();
} catch (IOException e) {
System.out.println(e.toString() + " :Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine, outputLine;
outputLine = nis.processAnswer(null);//get Learn Learn English line
out.println(outputLine);//and send the line out to client
nis.Jservertxt.setText(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = nis.processAnswer(inputLine);
out.println(outputLine);
nis.Jservertxt.setText(outputLine);
if (outputLine.equalsIgnoreCase("Don't miss me! Bye Bye!"))
break;
else if (outputLine.equalsIgnoreCase("Thank For Your Guessing. Have a Nice Day =)"))
break;
}
//End connection
out.flush();
out.close();
in.close();
nis.frame.setVisible(false);
if (!clientSocket.isClosed())
clientSocket.close();
nis.frame.setVisible(false);
if (!serverSocket.isClosed())
serverSocket.close();
nis.frame.setVisible(false);
System.out.println("TCP session closed.");
}
}
Here is my code for TCPProtocol.java
public volatile boolean getPressed;
Jsend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String Data = Jusertxt.getText();
Jusertxt.setText(null);
System.out.println(Data);
getPressed=true;
}
});
}
public boolean getPressed()
{
return getPressed;
}
i din't paste the full code here because i just show the part where do got problem.
and here is my TCPClient Code
import java.io.*;
import java.net.*;
public class TCPClient{
public static void main(String[] args) throws IOException, InterruptedException{
//TCP component
int port = 8081;
String host = "localhost";
Socket nisSocket = null;
PrintWriter out = null;
BufferedReader in = null;
TCPProtocol pro = new TCPProtocol();
try {
nisSocket = new Socket(host, port);
out = new PrintWriter(nisSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(nisSocket.getInputStream()));
} catch (UnknownHostException e) {
System.out.println(e.toString() + " :Don't know about " + host);
System.exit(1);
} catch (IOException e) {
System.out.println(e.toString() + " :Couldn't get I/O for the connection to " + host);
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer, fromUser;
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equalsIgnoreCase("Don't miss me! Bye Bye!"))
break;
if (fromServer.equalsIgnoreCase("Thank For Your Guessing. Have a Nice Day =)"))
break;
if (pro.getPressed())
{
fromUser = pro.Jusertxt.getText();
if (fromUser != null) {
System.out.println("\nClient: " + fromUser);
out.println(fromUser);
}
}
System.out.println("fail liao");
}
System.out.println("try again");
//End connection
out.flush();
out.close();
in.close();
stdIn.close();
//if (!nisSocket.isClosed())
nisSocket.close();
System.out.println("TCP session closed.");
}
}
So how can i only let the TCPClient.java process if only getPressed() method was true.
I try using volatile boolean variable but not working as well. Or should i use synchronized?
Solve after change to call GUI code from server to client
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equalsIgnoreCase("Don't miss me! Bye Bye!"))
break;
if (fromServer.equalsIgnoreCase("Thank For Your Guessing. Have a Nice Day =)"))
break;
pro.frame.setVisible(true);
pro.frame.setAlwaysOnTop(true);
pro.Jservertxt.setText(fromServer);
if(pro.getPressed()){
fromUser = pro.getMessage();
if (fromUser != null) {
System.out.println("\nClient: " + fromUser);
out.println(fromUser);
}
}
}
Here is a little example of a main thread (think of it as your TCPClient) that waits until user clicks button (think of this part as your TCPProtocol):
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class Test extends JFrame {
public Object lock = new Object();
private JTextArea area = new JTextArea();
public Test() {
super("test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton send = new JButton("send");
send.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
synchronized (lock) {
lock.notify();
}
}
});
add(area);
add(send, BorderLayout.SOUTH);
}
public String pullText() {
String result = area.getText();
area.setText("");
return result;
}
public static void main(String[] args) {
Test t = new Test();
t.setSize(200, 200);
t.setVisible(true);
while (true) {
synchronized (t.lock) {
try {
t.lock.wait();
System.out.println(t.pullText());
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Maybe you can apply a similar approach to your system.
Warning: this is just a quick and dirty example to give you the idea, please double check it. In general you should be very careful when dealing with synchronization.
EDIT:
As a starting point you can modify your TCPProtocol class (the part you posted) like this:
public volatile boolean getPressed;
private Object lock = new Object(); // added lock for wait/notify coordination
private String Data; //changed scope to make it accessible in getMessage()
Jsend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
synchronized(lock){
Data = Jusertxt.getText(); // no more a local variable, it's an instance attribute now, see declaration above
Jusertxt.setText(null);
System.out.println(Data);
getPressed=true;
lock.notify(); // notify client that user performed action
}
});
}
public boolean getPressed(){
synchronized (lock) {
try {
lock.wait(); // wait for user to perform action...
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
return getPressed; // ...then return value (I guess getPressed will always be true at this point)
}
public String getMessage(){ // call this in TCPClient instead of pro.Jusertxt.getText()
return Data;
}
I added a lock object to enable wait/notify mechanism and applied that to your actionPerformed and getPressed methods.
I also changed the scope of Data variable and I added a public method to get its value (getMessage()). If you doublecheck your code you'll see that you will always get null from pro.Jusertxt.getText() in TCPClient.java because you set it to null in actionPerformed. So change pro.Jusertxt.getText() to pro.getMessage() in TCPClient.java.
// [...]
fromUser = pro.getMessage(); // used to be fromUser = pro.Jusertxt.getText();
// [...]
If you get this raw version to work then you can refine and refactor it to make it more clean and consistent. (for instance, I suspect you don't actually need getPressed variable as it's actually always true)
I confess I didn't test this code so you might have to fix or adjust it a little, but I hope it can clarify how I meant you could apply the code I posted to your system.
Hope it helps.
Good luck :-)
You can try this:
while (!pro.getPressed()) {
System.out.println("still not true");
Thread.sleep(1000);
}
System.out.println("getPressed is true");

Java Multithreading for IVRS with GSM Modem rxtx (playing voice file making event listener stop working)

I have implemented a program to receive call using gsm modem. Upon Detecting "RING" call is answered an audio clip is played by calling a function from inside DATA_AVAILABLE EVENT HANDLER. But the event handler stops working after this. After the audio is complete Event Handler does not show any data received event anymore.
Why does the event listener stops working. Am I doing it wrong by playing the audio from inside the event handler? I was thinking about setting a variable true or false from inside data_received event handler and create custom event handler to listen to change to that variable to do playback of audio can these both work simultaneously in anyway?
How to create a multi threading solution So that Serial I/O is not interrupted and Audio Playback and Audio Sampling Can be done in a synchronised manner to detect dtmf tones.
Is there any way that serial port events can be listened to constantly without interruption and run a function for audio sampling and audio playback at specific time
Call Accepted in this case of switch and thread is started inside play() function
case SerialPortEvent.DATA_AVAILABLE:
StringBuffer sb = new StringBuffer();
byte[] readBuffer = new byte[2048];
try {
while (inputStream.available() > 0)
{
int numBytes = inputStream.read(readBuffer);
sb.append(new String(readBuffer,0,numBytes));
System.out.println(numBytes);
System.out.println(sb);
}
System.out.println("Data Available");
if((sb.toString()).contains("RING")){
System.out.println("Enter Inside if RING Loop");
//play();
send("ATA\r\n");
//welcomeMessage();
}
if((sb.toString()).contains("CARRIER")){
hangup();
//Thread.sleep(1000);
closePort();
outCommand();
System.out.println("Enter Inside if NO CARRIER Loop");
}
//print response message
System.out.print(sb.toString());
} catch (IOException e) {
}
break;
public void play() {
try {
new Thread() {
public void run() {
for(int i=0;i<1;i++)
welcomeMessage();
}
}.start();
} catch (Throwable e) {
e.printStackTrace();
}
}
Full Code
package sample;
import java.io.*;
import java.util.*;
import javax.sound.sampled.*;
import javazoom.jl.player.*;
import java.io.FileInputStream;
import gnu.io.*;
import java.io.*;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.apache.log4j.chainsaw.Main;
import sun.audio.*;
public class GSMConnect implements SerialPortEventListener,
CommPortOwnershipListener {
private static String comPort = "COM3"; // This COM Port must be connect with GSM Modem or your mobile phone
private String messageString = "";
private CommPortIdentifier portId = null;
private Enumeration portList;
private InputStream inputStream = null;
private OutputStream outputStream = null;
private SerialPort serialPort;
String readBufferTrial = "";
/** Creates a new instance of GSMConnect */
public GSMConnect(String comm) {
this.comPort = comm;
}
public boolean init() {
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
if (portId.getName().equals(comPort)) {
System.out.println("Got PortName");
return true;
}
}
}
return false;
}
public void checkStatus() {
send("AT+CREG?\r\n");
}
public void dial(String phoneNumber) {
try {
//dial to this phone number
messageString = "ATD" + phoneNumber + ";\r\n";
outputStream.write(messageString.getBytes());
System.out.println("Called ");
} catch (IOException e) {
e.printStackTrace();
}
}
public void send(String cmd) {
try {
outputStream.write(cmd.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String phoneNumber, String message) {
char quotes ='"';
send("AT+CMGS="+quotes + phoneNumber +quotes+ "\r\n");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// send("AT+CMGS=\""+ phoneNumber +"\"\r\n");
send(message + '\032');
System.out.println("Message Sent");
}
public void hangup() {
send("ATH\r\n");
}
public void welcomeMessage(){
// open the sound file as a Java input stream
String gongFile = "C:\\Users\\XXXX\\Desktop\\1-welcome.wav";
}*/
try{
FileInputStream fis = new FileInputStream("C:\\Users\\XXXX\\Desktop\\7001110.mp3");
Player playMP3 = new Player(fis);
playMP3.play();
System.out.print("welcomeMessage() Read");
}catch(Exception e){
System.out.println(e);
}
}
public void play() {
try {
new Thread() {
public void run() {
for(int i=0;i<1;i++)
welcomeMessage();
}
}.start();
} catch (Throwable e) {
e.printStackTrace();
}
}
public void connect() throws NullPointerException {
if (portId != null) {
try {
portId.addPortOwnershipListener(this);
serialPort = (SerialPort) portId.open("MobileGateWay", 2000);
serialPort.setSerialPortParams(115200,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
} catch (PortInUseException | UnsupportedCommOperationException e) {
e.printStackTrace();
}
try {
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
/** These are the events we want to know about*/
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
serialPort.notifyOnRingIndicator(true);
} catch (TooManyListenersException e) {
e.printStackTrace();
}
//Register to home network of sim card
send("ATZ\r\n");
} else {
throw new NullPointerException("COM Port not found!!");
}
}
public void serialEvent(SerialPortEvent serialPortEvent) {
System.out.println("serialPortEvent.getEventType()"+serialPortEvent.getEventType());
switch (serialPortEvent.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
// System.out.println("Ringing");
if( serialPortEvent.getNewValue() )
{
System.out.println("Ring Indicator On");
}
else
{
System.out.println("Ring Indicator Off");
}
break;
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
case SerialPortEvent.DATA_AVAILABLE:
StringBuffer sb = new StringBuffer();
byte[] readBuffer = new byte[2048];
try {
while (inputStream.available() > 0)
{
int numBytes = inputStream.read(readBuffer);
sb.append(new String(readBuffer,0,numBytes));
System.out.println(numBytes);
System.out.println(sb);
}
System.out.println("Data Available");
if((sb.toString()).contains("RING")){
System.out.println("Enter Inside if RING Loop");
//play();
send("ATA\r\n");
//welcomeMessage();
}
if((sb.toString()).contains("CARRIER")){
hangup();
//Thread.sleep(1000);
closePort();
outCommand();
System.out.println("Enter Inside if NO CARRIER Loop");
}
//print response message
System.out.print(sb.toString());
} catch (IOException e) {
}
break;
}
}
public void outCommand(){
System.out.print(readBufferTrial);
}
public void ownershipChange(int type) {
switch (type) {
case CommPortOwnershipListener.PORT_UNOWNED:
System.out.println(portId.getName() + ": PORT_UNOWNED");
break;
case CommPortOwnershipListener.PORT_OWNED:
System.out.println(portId.getName() + ": PORT_OWNED");
break;
case CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED:
System.out.println(portId.getName() + ": PORT_INUSED");
break;
}
}
public void closePort(){
serialPort.close();
}
public static void main(String args[]) {
GSMConnect gsm = new GSMConnect(comPort);
if (gsm.init()) {
try {
System.out.println("Initialization Success");
gsm.connect();
Thread.sleep(5000);
gsm.checkStatus();
Thread.sleep(5000);
// System.out.println("Before Auto Answer");
// gsm.send("ATS0=5");
// gsm.dial("87XXXXXSS");
// Thread.sleep(7500);
// System.out.println("After Auto Answer set");
// gsm.sendMessage("8XXXXXS56", "Trial Success Call me");
// gsm.sendMessage("80XXXXS56", "Trial Success Call me");
// gsm.sendMessage("8XXXXSXS6", "Trial Success Call me");
// Thread.sleep(5000);
// gsm.sendMessage("+919XXXXXXS3", "Third Msg");
// Thread.sleep(1000);
// gsm.dial("9XXXXS773");
// gsm.dial("871XXXXS5");
// Thread.sleep(1000);
// gsm.welcomeMessage();
// Thread.sleep(1000);
// gsm.welcomeMessage();// for turning on Echo ATE1&W
// Thread.sleep(20000);
// welcomeMessage();
// gsm.hangup();
// Thread.sleep(1000);
// gsm.closePort();
// gsm.outCommand();
// System.exit(1);
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Can't init this card");
}
}
}
Short of spending a good amount of time reproducing your environment I can give you two suggestions on how you might look into this.
a) Place a try-catch Throwable around your entire handler--often throwing exceptions can break event dispatchers
B) print out a debug statement when you enter and exit your event handler and ensure they are paired and that you get an exit after your last enter--a thread locking up will sometimes stop future events from being dispatched.
By the way you have an empty catch statement in one place--those scare the crap out of me because they often mask problems in ways that can waste days of your time. If you absolutely know you want to silently eat an exception there and you expect that exception to occur enough that it would pollute your logs to log it, please put a comment saying so.

System out/err streams in socket catch clause are working only in debug mode

Like in topic - System out and err streams seems to be "frozen" in catch clause in "update" method of Kernel class. Oddly when I am debuging the project and stop at System.out line I can even remove breakthrough and everything works correct.
Everything except last System.out is executed, it does not work even when I am replacing default System.out.
At the moment I am disconnecting user just after connection is made.
My code, StartServer.java:
public class StartServer {
public static void main (String[] args) {
Kernel kernel = new Kernel(4444);
kernel.run();
while (true) {
kernel.update();
}
}
}
Kernel.java:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Kernel {
ArrayList<Socket> clients;
ServerSocket socket;
public Kernel(int port) {
try {
socket = new ServerSocket(port);
clients = new ArrayList<>();
System.out.println("Server initialized");
} catch (IOException ex) {
Logger.getLogger(StartServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void run() {
Thread thread = new Thread(){
public void run() {
try {
while (true) {
Socket client = socket.accept();
clients.add(client);
System.out.println("New user on the server!");
}
} catch (IOException ex) {
Logger.getLogger(Kernel.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
thread.start();
}
public void update() {
for (int i=0; i<clients.size(); i++) {
Socket s = clients.get(i);
try {
/*String result;
if (s.getInputStream().available()!=0) {
byte[] byteRes = new byte[s.getInputStream().available()];
char[] charRes = new char[s.getInputStream().available()];
s.getInputStream().read(byteRes);
for (int i2=0; i2<charRes.length; i2++) {
charRes[i2] = (char) byteRes[i2];
}
result = String.copyValueOf(charRes);
System.out.println(result);
}*/
throw new IOException();
} catch (IOException ex) {
try {
System.out.println("Client disconnected"); //working only in debug mode
clients.remove(s);
s.close();
i--;
} catch (IOException ex1) {
Logger.getLogger(Kernel.class.getName()).log(Level.SEVERE, null, ex1);
}
}
}
}
}
Change your infinite loop in StartServer class as below:
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
kernel.update();
}
Try to add a
System.out.flush();
after the System.out.println()

Categories

Resources