Wait Until Condition become true - java

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");

Related

The read from a TCP Server hangs when reading more than once

I am testing some TCP code and it seems to work fine except for one problem. The read from the socket hangs in one of the methods when there is nothing more to read:
Here is the TCP code:
package com.comp424.service;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TCPService implements Runnable
{
protected int serverPort;
protected InetAddress bindAddress;
protected ServerSocket serverSocket = null;
protected boolean isStopped = false;
protected Thread runningThread = null;
protected ExecutorService threadPool = Executors.newFixedThreadPool(10);
public TCPService(String host,int port)
{
serverPort = port;
try
{
bindAddress = InetAddress.getByName(host);
}
catch (UnknownHostException e)
{
throw new RuntimeException("Failed to get bind address", e);
}
}
private void start()
{
try
{
serverSocket = new ServerSocket(serverPort, 10, bindAddress);
}
catch (IOException e)
{
throw new RuntimeException("Cannot open port " + serverPort, e);
}
}
public void run()
{
synchronized (this)
{
runningThread = Thread.currentThread();
}
start();
while (!isStopped())
{
Socket clientSocket = null;
try
{
clientSocket = serverSocket.accept();
}
catch (IOException e)
{
if (isStopped())
{
System.out.println("Server Stopped.");
break;
}
throw new RuntimeException("Error accepting client connection", e);
}
threadPool.execute(new ClientHandler(clientSocket));
}
threadPool.shutdown();
System.out.println("Server Stopped.");
}
public synchronized void stop()
{
isStopped = true;
try
{
serverSocket.close();
}
catch (IOException e)
{
throw new RuntimeException("Error closing server", e);
}
}
private synchronized boolean isStopped()
{
return isStopped;
}
}
package com.comp424.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import com.comp424.impl.dao.DaoFactory;
import com.comp424.intf.dao.ICourseDao;
import com.comp424.intf.dao.IPersonDao;
import com.comp424.intf.dao.IRegisterCourseDao;
import com.comp424.model.Course;
import com.comp424.model.Person;
public class ClientHandler implements Runnable
{
private static IRegisterCourseDao registrationDao;
private static IPersonDao personDao;
private static ICourseDao courseDao;
protected Socket clientSocket = null;
public ClientHandler(Socket socket)
{
registrationDao = DaoFactory.getInstance().getCourseRegistrationDao();
personDao = DaoFactory.getInstance().getPersonDao();
courseDao = DaoFactory.getInstance().getCourseDao();
clientSocket = socket;
}
public void run()
{
try
{
String command = null;
OutputStream output = clientSocket.getOutputStream();
BufferedReader buffer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
command = buffer.readLine();
while (command != null)
{
String separator = ":";
StringTokenizer tokenizer = new StringTokenizer(command, separator);
List<String> tokens = new ArrayList<>();
while (tokenizer.hasMoreElements())
{
tokens.add((String) tokenizer.nextElement());
}
int operation = Integer.parseInt(tokens.get(0));
switch (operation)
{
case 1:
try
{
Person person = personDao.findByID(Long.parseLong(tokens.get(1)));
Course course = courseDao.findByID(Long.parseLong(tokens.get(2)));
registrationDao.register(person, course);
output.write(("0\r\n").getBytes());
}
catch (Exception e)
{
e.printStackTrace();
output.write(("1\r\n").getBytes());
}
break;
case 2:
try
{
Person person = personDao.findByID(Long.parseLong(tokens.get(1)));
Course course = courseDao.findByID(Long.parseLong(tokens.get(2)));
registrationDao.register(person, course);
output.write(("0\r\n").getBytes());
}
catch (Exception e)
{
e.printStackTrace();
output.write(("1\r\n").getBytes());
}
break;
case 3:
try
{
Person person = personDao.findByID(Long.parseLong(tokens.get(1)));
List<Course> courses = registrationDao.findByPerson(person);
for (Course c : courses)
{
output.write((c.getName() + "\r\n").getBytes());
}
}
catch (Exception e)
{
e.printStackTrace();
output.write(("1\r\n").getBytes());
}
break;
}
command = buffer.readLine();
}
output.close();
}
catch (IOException e)
{
// report exception somewhere.
e.printStackTrace();
}
}
}
And here is the code where it just hangs in findRegisteredCourses() after reading two strings returned instead of exiting the while loop:
while (response != null)
{
result.add(response);
System.out.println("findRegisteredCourses():Response = " + response);
response = reader.readLine();
}
Full code for findRegisteredCourses():
#Override
public List<String> findRegisteredCourses(String personID) throws Exception
{
try (Socket server = new Socket("localhost", 7000))
{
List<String> result = new ArrayList<>();
DataOutputStream writer = new DataOutputStream(server.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream()));
String operation = "3:" + personID + "\r\n";
writer.writeBytes(operation);
writer.flush();
String response = reader.readLine();
while (response != null)
{
result.add(response);
System.out.println("findRegisteredCourses():Response = " + response);
response = reader.readLine();
}
server.close();
return result;
}
}
You're continuing to try to read from the server until it's closed the socket - whereas the server is waiting for another command from the client. Neither side is going to do anything, as they're waiting for the other.
Basically, you need to change your protocol, either to have some "here's the end of the response" indication (such as an empty line, if that's not a valid value in the response data), or to only have a single request/response per connection.
Your suggested "fix" of using the ready() method is very broken - it basically means you assume there's no more data as soon as there's a pause. Maybe the server is taking a while to find the next item. Maybe there's a delay on the network - or maybe it's finished. You can't tell, and basically you're violating the design of streaming protocols (such as TCP) by trying to infer information from the fact that there's no data available right now. Don't do that - fix your protocol.
Deleted my original answer because it was wrong as per #Jon Skeet's comments. I now just send a special end of data token and it works fine.

How can I break an infinite loop at runtime?

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.

How to make server and client in java?

I i am making a server/client but there seems to be a problem. I cannot seem to connect when i click the button.Please help.Not sure what i did wrong.Feel free to edit code to fix it then comment please.I have a connect button,and a send button. I think it has something to do with the highlighted code but it could be anything. I know this isnt very specific but basically heres the code and it doesnt work. I cant connect . please help!
Client
public class chat_client extends javax.swing.JFrame {
String username;
Socket sock;
BufferedReader reader;
PrintWriter writer;
ArrayList<String>userList = new ArrayList();
Boolean isConnected = false;
public chat_client() {
initComponents();
getContentPane().setBackground(Color.white);
this.setIconImage(new ImageIcon(getClass()
.getResource("dogeIcon.jpg")).getImage());
this.setLocationRelativeTo(null);
}
public class IncomingReader implements Runnable{
public void run(){
String stream;
String[] data;
String done = "Done", connect = "Connect",
disconnect = "Disconnect", chat = "Chat";
try {
while ((stream = reader.readLine()) != null){}
data = stream.split("^");
if (data[2].equals(chat)){
txtChat.append(data[0] + ":" + data[1] + "\n");
} else if (data[2].equals(connect)){
txtChat.removeAll();
userAdd(data[0]);
} else if (data[2].equals(disconnect)){
userRemove(data[0]);
} else if (data[2].equals(done)){
userList.setText("");
writeUsers();
}
} catch(Exception ex){
}
}
}
public void ListenThread(){
Thread IncomingReader = new Thread(new IncomingReader());
IncomingReader.start();
}
public void userAdd(String data){
userList.add(data);
}
public void userRemove(String data){
txtChat.append(data + " has disconnected \n");
}
public void writeUsers(){
String[] tempList = new String[(userList.size())];
userList.toArray(tempList);
for (String token:tempList){
userList.append(token + "\n");
}
}
public void sendDisconnect(){
String bye = (username + "^ ^Disconnected");
try{
writer.println(bye);
writer.flush();
} catch(Exception e){
txtChat.append("Could Not Send Disconnect Message \n");
}
}
public void Disconnect(){
try{
txtChat.append("Disconnected\n");
sock.close();
} catch(Exception ex){
txtChat.append("Failed to disconnect\n");
}
isConnected = false;
txtUser.setEditable(true);
userList.setText("");
}
(This is the highlighted part where i think the problem is)
***private void connectActionPerformed(java.awt.event.ActionEvent evt) {
if (isConnected == false){
username = txtUser.getText();
txtUser.setEditable(false);
try{
sock = new Socket("localhost", 1023);
InputStreamReader streamreader
= new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(streamreader);
writer = new PrintWriter(sock.getOutputStream());
writer.println(username + "^has connected.^Connect");
writer.flush();
isConnected = true;
} catch(Exception ex){
txtChat.append("Cannot Connect! Try Again\n");
txtUser.setEditable(true);
}
ListenThread();
} else if (isConnected == true){
txtChat.append("You is connected bra\n");
}
}***
(Ends here-the problem/highlighted part)
private void btn_SendActionPerformed(java.awt.event.ActionEvent evt) {
String nothing = "";
if ((txtMsg.getText()).equals(nothing)){
txtMsg.setText("");
txtMsg.requestFocus();
} else {
try{
writer.println(username + "^" + txtMsg.getText() + "^"
+ "Chat");
writer.flush();
} catch (Exception ex){
txtChat.append("Message was not sent\n");
}
txtMsg.setText("");
txtMsg.requestFocus();
}
A couple things:
You're getting a java.net.ConnectionException (see below) because the connection is being refused. This could be because the server you are trying to connect to is not running, the server is not accepting client connections, the server is not accessible by the client, or you are connecting to the wrong port number.
It is generally bad coding practice to catch Exception directly. You want to either catch the most specific exception that ranges across the variety of exceptions that can be thrown (in this case, IOException) or catch each possible one individually, which is the preferred method. Catch the most specific exceptions before the more general ones so that they are not masked by them. Furthermore it is a good idea to use the Throwable class's getMessage() method so that you can figure out the reason for the exception being thrown. For example:
} catch (java.net.ConnectException ex) {
System.err.println("ConnectException: " + ex.getMessage()); // May return "Connection refused", "Connection timed out", "Connection reset", etc.
} catch (java.rmi.UnknownHostException ex) {
System.err.println("UnknownHostException: " + ex.getMessage()); // Returns the name of the host you were attempting to connect to
} catch (...) {
// code here
} catch (java.io.IOException ex) {
System.err.println("IOException: " + ex.getMessage()); // May return a problem with the BufferedReader or InputStreamReader or PrintWriter
}
Of course, the statements in the catch clause can be modified to your liking.

chat in java not synchronized (sockets, threads)

I'm trying to figure out a way to get an instance of a server to negotiate between two clients by creating a chat thread between them.
I created this project, and it "almost" works... but it seems like there is a buffer of synch problem.
when writing a line in one side (i.e Client#1), it doesn't pass to the other side (i.e Client#2), but only after Client#2 trys to pass a line too.
I know there might be better ways to implement this, but I'd like to understand what's wrong with my code.
your help would be great!
the code:
server
import java.io.*;
import java.net.*;
public class Server
{
public static void main(String[] args)
{
int id = 1;
System.out.println();
System.out.println("Server");
try
{
ServerSocket serverSocket = new ServerSocket(4321);
while (true)
{
Socket client1Socket = serverSocket.accept();
Socket client2Socket = serverSocket.accept();
System.out.println("clients connected from ports: \n"
+ client1Socket.getPort() + ", " + client2Socket.getPort());
Thread client1Thread = new ServerThread(client1Socket, client2Socket, id);
client1Thread.start();
id++;
Thread client2Thread = new ServerThread(client2Socket, client1Socket, id);
client2Thread.start();
id++;
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
server thread
import java.io.*;
import java.net.*;
import java.util.*;
public class ServerThread extends Thread
{
Socket sourceSocket;
Socket destSocket;
int id;
public ServerThread(Socket src, Socket dst, int n)
{
sourceSocket = src;
destSocket = dst;
id = n;
}
public void run()
{
try
{
Scanner clientInput = new Scanner(sourceSocket.getInputStream());
PrintStream destOutput = new PrintStream(destSocket.getOutputStream());
destOutput.println("You are chatting with Client " + id);
boolean more = true;
while (more)
{
String input = clientInput.nextLine();
destOutput.println(input);
if (input.equals("Q"))
{
more = false;
}
}
sourceSocket.close();
destSocket.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
client
import java.io.*;
import java.net.*;
import java.util.*;
public class Client
{
public static void main(String[] args)
{
System.out.println();
System.out.println("Client");
try
{
Socket clientSocket = new Socket("localhost", 4321);
System.out.println("Connection Established");
Scanner input = new Scanner(clientSocket.getInputStream());
PrintStream output = new PrintStream(clientSocket.getOutputStream());
Scanner in = new Scanner(System.in);
System.out.println(input.nextLine());
boolean more = true;
while (more)
{
String text = in.nextLine();
output.println(text);
String nextInput = input.nextLine();
if (nextInput == null)
{
more = false;
}
else
{
System.out.println(nextInput);
}
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
In your client code, the line String text = in.nextLine(); will block your thread. That means if you never type in anything in your client, you can not receive anything. So the solution is to put your message receiving code in another thread. such as:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (!Thread.interrupted()) {
System.out.println(input.nextLine());
}
}
});
thread.start();
while (true)
{
String text = in.nextLine();
output.println(text);
// String nextInput = input.nextLine();
......................
}

Program won't continue after initializing input/output streams?

Before people suspect that I have no idea what I'm doing at all (and end up voting this down for no reason at all), please read this:
It connects to my server just fine! I'm getting no errors (from the client OR server), and my server is recognizing the connection. It works with my friend's client that he made, but I wanted to make my own client, and apparently I'm doing something wrong. PLEASE STAY ON TOPIC! Thanks :)
Title basically says it all. I've tested with println messages above and below the setupStream() in my Client.java run(), but only the message above the setupStream() prints. I'm not sure how I'm supposed to initialize my stream without making my program come to a halt.
Client.java
import java.io.IOException;
public class Client extends Stream implements Runnable {
public boolean running = false;
private Thread clientThread;
Frame frame;
public Client() {
super("localhost", 43594);
frame = new ClientFrame(500, 500);
start();
}
public synchronized void start() {
if(running) return;
running = true;
clientThread = new Thread(this);
clientThread.start();
}
public synchronized void stop() {
if(!running) return;
running = false;
clientThread.interrupt();
try {
clientThread.join();
} catch (InterruptedException e) {e.printStackTrace();}
}
public void run() {
try{
setupStream();
while(running) {
System.out.println("running");
}
}catch(IOException e) {
e.printStackTrace();
}finally {
try{
out.close();
in.close();
socket.close();
clientThread.join();
}catch(IOException | InterruptedException e) { e.printStackTrace(); }
}
}
public static void main(String[] args) {
new Client();
}
}
Stream.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class Stream {
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
String data;
public Stream(String host, int port) {
try {
socket = new Socket(host, port);
} catch (IOException e) {
e.printStackTrace();
}
}
protected void setupStream() throws IOException {
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());
}
}
My Server Thread:
package Server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
public class User extends Thread {
public static int users = 0;
public int ID;
public String username;
boolean online = false;
public static ArrayList<String> usernames = new ArrayList<String>();
Socket socket;
DataOutputStream out;
DataInputStream in;
String input;
public User(Socket socket) {
this.socket = socket;
}
public String decode(String input) {
String[] split = input.split(" ");
if(input.startsWith("::")) {
try {
switch(split[0].substring(2, split[0].length()).toLowerCase()) {
case "setname":
case "changename":
case "newname":
if(usernames.contains(split[1].toLowerCase())) {
out.writeUTF("This name is already taken! Please choose a different one.");
out.flush();
return null;
}
if(username == null) {
username = split[1].substring(0, 1).toUpperCase() + split[1].substring(1, split[1].length());
Server.users.put(split[1].toLowerCase(), Server.user[ID]);
usernames.add(split[1].toLowerCase());
} else {
usernames.remove(username.toLowerCase());
username = split[1].substring(0, 1).toUpperCase() + split[1].substring(1, split[1].length());
usernames.add(split[1].toLowerCase());
}
return null;
case "rank+":
return null;
case "[sm]=":
return null;
}
}catch(IOException e) { }
}
return input;
}
String timeStamp;
public void run() {
try {
out = new DataOutputStream(socket.getOutputStream());
out.flush();
in = new DataInputStream(socket.getInputStream());
while((input = in.readUTF()) != null) {
input = decode(input);
if(input != null) {
if(username != null) {
timeStamp = new SimpleDateFormat("[h:mm:ss] ").format(Calendar.getInstance().getTime());
Server.sendGlobalMessage(timeStamp + username +": "+input);
} else {
timeStamp = new SimpleDateFormat("[h:mm:ss] ").format(Calendar.getInstance().getTime());
Server.sendGlobalMessage(timeStamp + "Guest "+ID+": "+input);
}
}
}
}catch(IOException e) { e.printStackTrace(); } finally {
try{
out.close();
in.close();
socket.close();
} catch(IOException e) { e.printStackTrace(); }
}
}
}
I haven't touched the code of my Server Thread for a while, since it has always worked up until I made my new client.
I suspect that your server does not create an ObjectOutputStream, so when the client constructs its ObjectInputStream, it blocks waiting for the object stream header, which never arrives.

Categories

Resources