I made a client-server application where the server has to send a list of emails to the client, which after load that into a ListView gives the possibility, through a menuBar, to delete them. In the client all these operations are made in the Data Model (I followed the MVC pattern). This is the server:
class ThreadedEchoHandler implements Runnable {
private Socket incoming;
private String nomeAccount = "";
public void run() {
try {
incoming = s.accept();
} catch (IOException ex) {
System.out.println("Unable to accept requests");
}
contenutoTextArea.append("Connected from: " + incoming.getLocalAddress() + "\n");
textarea.setText(contenutoTextArea.toString());
try {
//PHASE 1: The server receives the email
try {
BufferedReader in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
nomeAccount = in.readLine();
} catch (IOException ex) {
System.out.println("Not works");
}
//PHASE 2: I'm getting all the emails from the files
File dir = new File("src/server/" + nomeAccount);
String[] tmp = new String[100];
int i = 0;
for (File file : dir.listFiles()) {
if (file.isFile() && !(file.getName().equals(".DS_Store"))) {
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
tmp[i++] = line;
}
} catch (IOException ex) {
System.out.println("Cannot read from file");
}
}
}
//PHASE 3: The server sends the ArrayList to the client
PrintWriter out = new PrintWriter(incoming.getOutputStream(), true);
for (int j = 0; j < i; j++) {
out.println(tmp[j]); // send the strings to the client
}
} catch (IOException ex) {
System.out.println("Cannot send the strings to the client");
}
//PHASE 4: Here I loop and wait for the client choise
BufferedReader in;
String op;
try {
in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
while ((op = in.readLine()) != null) {
if (op.equals("Elimina")) {
String tmp = in.readLine();
File file = new File("src/server/" + nomeAccount + "/" + tmp + ".txt");
file.delete();
} else if (op.equals("Invia")) {
//...
} else {
//...
}
}
} catch (IOException ex) {
System.out.println("Non so");
} finally {
try {
incoming.close();
} catch (IOException ex) {
System.out.println("Cannot closing the socket");
}
}
}
}
These are the methods of the client:
public void loadData() throws IOException, ClassNotFoundException, ParseException {
try {
s = new Socket("127.0.0.1", 5000);
ArrayList<Email> email = new ArrayList<Email>();
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
Date data;
/* PHASE 1: The client sends a string to the server */
//try {
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
out.println(account); // send the account name to server
/* PHASE 2: The client receives the ArrayList with the emails */
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
String message[] = new String[5];
for (int j=0; (line = in.readLine()) != null;) {
message[j++] = line;
if (j==5) {
data = format.parse(message[3]);
email.add(new Email((Integer.parseInt(message[0])), message[1], account, message[2], message[4], data));
j=0;
}
}
//Casting the arrayList
emailList = FXCollections.observableArrayList(email);
//Sorting the emails
Collections.sort(emailList, (Email o1, Email o2) -> {
if (o1.getData() == null || o2.getData() == null) {
return 0;
}
return o1.getData().compareTo(o2.getData());
});
/*} finally {
s.close();*/
//}
} catch (SocketException se) {
emailList.setAll(null, null);
}
}
public void deleteMail(Email da_elim) throws IOException {
int id_del = da_elim.getID();
emailList.remove(da_elim);
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
out.println("Elimina");
out.println(id_del);
}
The PHASE 1, 2, 3 of the Server are for the upload of the emails, and work with the loadData() method. Without the PHASE 4 the program works. Now, if I write that loop, the GUI of the client doesn't load and I cannot press on the DELETE button (which should make the input to innescate something (in this the elimination of the file) into that loop. Why the client doesn't load even if they are two different threads? And why without that loop it works?
EDIT: with the Listener class implemented but still doesn't works
//PHASE 4: Here I loop and wait for the client choise
BufferedReader in;
String op;
try {
in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
/*while ((op = in.readLine()) != null) {
System.out.println("OP: " + op);
if (op.equals("Elimina")) {
String tmp = in.readLine();
contenutoTextArea.append("Ho eliminato la mail ").append(tmp).append(" \n");
textarea.setText(contenutoTextArea.toString());
File file = new File("src/server/" + nomeAccount + "/" + tmp + ".txt");
file.delete();
}
}*/
Listener lis = new Listener(in, new LinkedBlockingQueue<String>());
lis.run();
System.out.println("bbbbb");
} catch (IOException ex) {
System.out.println("Unable to read messages");
} finally {
try {
incoming.close();
} catch (IOException ex) {
System.out.println("Cannot close the socket");
}
}
I think you should run jvisualvm (it's a tool installed with jdk in /bin/ location of your jdk) and look for that Thread lifecycle you create on server. Also check if your Thread don't go through the code and just ends his life skipping waiting for client.
Is this Thread somehow connected with client? Because you cannot run client App. Are they separated? Another think that came to my mind is using
Platform.runLater(()->{
});
if your client GUI is in JavaFX. Use it if you are creating GUI, changing values in fields and anything you do on your GUI. Maybe your server is waiting for user response and after that GUI is built? Which causes that you can't press DELETE button.
I'm not currently able to comment, so I can't ask for clarification, but I think I'm correctly interpreting what's wrong. "The program hangs when it enters a loop that waits for input from two controllers". Assuming I got that part right, the most likely culprit would be that buffered reader is hanging indefinitely because its not receiving input. When I first ran into this issue, I threw it inside its own "receiver" class and used a Queue to bus over anything it received to a loop in my main class. my code looked something like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
public class Listener implements Runnable
{
private BufferedReader br;
private BlockingQueue<String> q;
private boolean shouldClose = false;
public Listener(BufferedReader br, BlockingQueue<String> q)
{
this.q = q;
this.br = br;
}
public void run()
{
loop();
System.out.println("listener has stopped");
}
public void loop()
{
String line = "";
try
{
while((line = br.readLine()) != null && !shouldClose)
{
q.put(line);
}
}
catch (IOException | InterruptedException e)
{
e.printStackTrace();
}
}
public void shutdown()
{
shouldClose = true;
}
}
apologies if I've misunderstood in any way, or missed something in your code.
Related
I've been working on a university project for a bit where I essentially coded a GUI along with a few other features on it. Recently, we've been tasked with implementing a server/client communication on the application, and the topic hasn't really been explained very well to us so I have been struggling. My idea for the implementation is to take the username & password that the client provides at the login screen, send it to a Server class, verify the details, and then send a boolean value of either true or false, depending on whether or not they have the correct details. This hasn't worked, and I don't believe the username/password test variables in the server class take on any values. I will share the relevant snippets of code from both the Client & Server class down below.
Client Part:
private void loginMessage() {
/*
* This is the default login message that will be displayed. We could add
* checkers and such to the information we receive from the username/password
* fields, however that is outside of the scope of our current homework
* assignment. I did, however, make sure to store the username in a string and
* personalize the welcome message.
*/
String uName = txtUsername.getText();
try {
dout.writeUTF(uName);
} catch (Exception e) {
}
String password = new String(usPassword.getPassword());
try {
dout.writeUTF(password);
} catch (Exception e) {
}
try {
boolean loginSuccess = din.readBoolean();
if (loginSuccess) {
JOptionPane.showMessageDialog(this,
"Thank you for logging in " + uName
+ ". You will now get redirected to our Customer Zone, where you can make purchases. Press OK to continue.",
"Success!", JOptionPane.INFORMATION_MESSAGE);
finished = true;
} else {
JOptionPane.showMessageDialog(this,
"Error. Either your username or password is incorrect. Please try again.", "Error",
JOptionPane.ERROR_MESSAGE);
}
} catch (Exception e) {
}
}
private void cancel() {
/*
* This is the cancel operation. We will close the application when the cancel
* option is selected.
*/
System.exit(1);
}
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 7000);
InputStream in = socket.getInputStream();
DataInputStream din = new DataInputStream(in);
// send a message from client to server
OutputStream out = socket.getOutputStream();
DataOutputStream dout = new DataOutputStream(out);
} catch (Exception e) {
}
// We define a new MyApplication object in order to run our application.
MyApplication x = new MyApplication();
Progress a = new Progress();
Secondpage s = new Secondpage();
Thread t1 = new Thread(x);
t1.start();
try {
t1.join();
} catch (Exception e) {
e.printStackTrace();
}
a.start();
try {
a.join();
} catch (Exception e) {
e.printStackTrace();
}
s.start();
try {
s.join();
} catch (Exception e) {
e.printStackTrace();
}
}
Server Part:
public class MyServer {
Socket serverSocket;
BufferedReader br;
FileReader fr;
static String uname;
static String pwd;
static String filepath = "login.txt";
static String sep = ",";
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(7000);
System.out.println("Waiting for a client...");
Socket mySocket = serverSocket.accept();
System.out.println("I have a client");
DataInputStream clientIn = new DataInputStream(mySocket.getInputStream());
DataOutputStream clientOut = new DataOutputStream(mySocket.getOutputStream());
uname = clientIn.readUTF();
pwd = clientIn.readUTF();
System.out.println("I have a username " + uname + pwd);
boolean verif = verifyUserLogin(uname, pwd, filepath, sep);
clientOut.writeBoolean(verif);
System.out.println("Username: " + uname);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static boolean verifyUserLogin(String user, String pwd, String fp, String sep) {
String currentLine;
String data[];
try {
// We use FileReader to read file, and BufferedReader to read character stream.
FileReader fr = new FileReader(fp);
try (BufferedReader br = new BufferedReader(fr)) {
while ((currentLine = br.readLine()) != null) {
data = currentLine.split(sep);
if (data[0].equals(user) && data[1].equals(pwd)) {
return true;
}
}
}
} catch (Exception e) {
}
return false;
}
}
Now, my issue is I am struggling with sending the login and password strings over to the server. I don't think the username & password variables in the Server class are even holding any values to be honest, and I am unsure of how to fix this. I'm kind of lost, and really need some help. Thank you very much :)
I have a situation with a Java Socket Input reader.
I am trying to develop an URCAP for Universal Robots and for this I need to use JAVA.
The situation is as follow:
I connect to the Dashboard server through a socket on IP 127.0.0.1, and port 29999.
After that the server send me a message "Connected: Universal Robots Dashboard Server".
The next step I send the command "play".
Here starts the problem. If I leave it like this everything works.
If I want to read the reply from the server which is "Starting program" then everything is blocked.
I have tried the following:
-read straight from the input stream-no solution
-read from an buffered reader- no solution
-read into an byte array with an while loop-no solution
I have tried all of the solution presented here and again no solution for my case.
I have tried even copying some code from the Socket Test application and again no solution.
This is strange because as mentioned the Socket Test app is working with no issues.
Below is the link from the URCAP documentation:
https://www.universal-robots.com/articles/ur/dashboard-server-cb-series-port-29999/
I do not see any reason to post all the trials code because I have tried everything.
Below is the last variant of code maybe someone has an idea where I try to read from 2 different buffered readers. The numbers 1,2,3 are there just so I can see in the terminal where the code blocks.
In conclusion the question is: How I can read from a JAVA socket 2 times?
Thank you in advance!
public void sendPlay() {
try {
// Create a new Socket Client
Socket sc = new Socket("127.0.0.1", 29999);
if (sc.isConnected()) {
InputStream is = sc.getInputStream();
BufferedInputStream in = new BufferedInputStream(is);
String data = "";
int s = in.read();
data += ""+(char)s;
int len = in.available();
System.out.println("Len got : "+len);
if(len > 0) {
byte[] byteData = new byte[len];
in.read(byteData);
data += new String(byteData);
}
System.out.println(data);
System.out.println("1");
// Create stream for data
DataOutputStream out;
out = new DataOutputStream(sc.getOutputStream());
String command = new String();
command = "play"+"\n";
// Send command
out.write(command.getBytes("US-ASCII"));
out.flush();
System.out.println("2");
InputStream is1 = sc.getInputStream();
BufferedInputStream in1 = new BufferedInputStream(is1);
String data1 = "";
int s1 = in1.read();
data1 += ""+(char)s1;
int len1 = in1.available();
System.out.println("Len got : "+len1);
if(len1 > 0) {
byte[] byteData1 = new byte[len1];
in.read(byteData1);
data1 += new String(byteData1);
}
System.out.println(data1);
System.out.println("3");
// Perform housekeeping
out.close();
sc.close();
}
sc.close();
} catch (IOException e) {
System.out.println(e);
}
}
The problem seems to be that you are opening several input streams to the same socket for reading commands.
You should open one InputStream for reading, one OutputStream for writing, and keep them both open till the end of the connection to your robot.
Then you can wrap those streams into helper classes for your text-line based protocol like Scanner and PrintWriter.
Sample program to put you on track (can't test with your hardware so it might need little tweaks to work):
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class RobotTester implements AutoCloseable {
private Socket clientSocket;
private Scanner inputReader;
private PrintWriter outWriter;
private int incounter;
private int outcounter;
public static void main(String[] args) {
System.out.println("Program started. Connecting to robot");
try (RobotTester robot = new RobotTester("127.0.0.1", 29999)) {
System.out.println("Connected to robot.");
robot.nextInput(); //Read and print robot's welcome message
robot.writeCommand("play"); //Send command
String resp = robot.nextInput(); //Read result
if (resp.toLowerCase().startsWith("fail")) {
throw new Exception("Play command failed: " + resp);
}
System.out.println("Command succeeded!");
} catch (Throwable t) {
t.printStackTrace();
}
}
public RobotTester(String host, int port) throws UnknownHostException, IOException {
clientSocket = new Socket(host, port);
inputReader = new Scanner(clientSocket.getInputStream());
outWriter = new PrintWriter(clientSocket.getOutputStream());
}
public String nextInput() {
String mess = inputReader.nextLine();
System.out.println("< " + (++incounter) + ": " + mess);
return mess;
}
public void writeCommand(String command) {
System.out.println("> " + (++outcounter) + ": " + command);
outWriter.print(command);
outWriter.print('\n');
outWriter.flush();
}
#Override
public void close() throws Exception {
if (inputReader != null) {
inputReader.close();
inputReader = null;
}
if (outWriter != null) {
outWriter.close();
outWriter = null;
}
if (clientSocket != null) {
clientSocket.close();
clientSocket = null;
}
}
}
In addition, you're using 127.0.0.1 as server IP address, which is the loopback on your PC. Unless the interface to your robot works in a very peculiar way, the actual IP you should use is probably not this one.
I'm refering to this part of documentation here:
Setup a static IP-address and subnet mask on PC, so it matches the
robot, e.g.:
PC: IP-addr: 192.168.3.10 Robot: IP-addr: 192.168.3.3
Subnet: 255.255.255.0 Subnet: 255.255.255.0
Edit
If you've got more commands to put, use it like this:
//Inside your actual main class
public static void main(String[] args) {
System.out.println("Program started. Connecting to robot");
try (RobotTester robot = new RobotTester("127.0.0.1", 29999)) {
System.out.println("Connected to robot.");
robot.nextInput(); //Read and print robot's welcome message
robot.writeCommand("play"); //Send command
String resp = robot.nextInput(); //Read result
if (resp.toLowerCase().startsWith("fail")) {
throw new Exception("Play command failed: " + resp);
}
System.out.println("Command succeeded!");
robot.writeCommand("command1"); //Send command
resp = robot.nextInput(); //Read result
//Process result for command1
robot.writeCommand("command2"); //Send command
resp = robot.nextInput(); //Read result
//Process result for command2
//...
} catch (Throwable t) {
t.printStackTrace();
}
}
The latest update is that I have moved all the functions in the same Dialog and just called them straight from there, and is still not working.
I already double check there is just one stream and one writer and reader in the entire project.
JButton btnNewButton_2 = new JButton("START");
btnNewButton_2.setBackground(Color.GREEN);
btnNewButton_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
RobotTester("127.0.0.1", 29999);
nextInput();
String command="play";
writeCommand(command);
nextInput();
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
close();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} });
public void RobotTester(String host, int port) throws UnknownHostException, IOException {
clientSocket = new Socket(host, port);
inputReader = new Scanner(clientSocket.getInputStream());
outWriter = new PrintWriter(clientSocket.getOutputStream());
}
public String nextInput() {
String mess = inputReader.nextLine();
System.out.println("< " + (++incounter) + ": " + mess);
return mess;
}
public void writeCommand(String command) {
System.out.println("> " + (++outcounter) + ": " + command);
outWriter.print(command);
outWriter.print('\n');
outWriter.flush();
}
public void close() throws Exception {
if (inputReader != null) {
inputReader.close();
inputReader = null;
}
if (outWriter != null) {
outWriter.close();
outWriter = null;
}
if (clientSocket != null) {
clientSocket.close();
clientSocket = null;
}
}
I have found a solution to the issue of reading the from the socket multiple times with a Swing GUI.
public void sendPlay() {
Thread appThread = new Thread() {
public void run() {
try {
RobotTester robot = new RobotTester("127.0.0.1", 29999);
System.out.println("Connected to robot.");
robot.nextInput(); //Read and print robot's welcome message
robot.writeCommand("play"); //Send command
String resp = robot.nextInput(); //Read result
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Finished on " + Thread.currentThread());
}
};
appThread.start();}
It seems that the background socket reading needs to be on a separate thread. This was causing the entire robot to be blocked. The idea was from an forum. It was not mine, but hey, it works.
Thank you very much!
I'm trying to make a server/client to send text from client to server then sending back an ok message or something similar back to the client, but for some error that I can't see, either the server gets stuck right before sending the ok back to the client, or the client does not receive the message (I think it's the first one though).
Any help is appreciated.
This is the server code:
class ActiveServer extends Thread {
InputStream inStream;
OutputStream outStream;
public ActiveServer(InputStream inStream, OutputStream outStream) {
this.inStream = inStream;
this.outStream = outStream;
}
#Override
public void run() {
boolean ret = false;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
PrintWriter writer = new PrintWriter(outStream);) {
String line = null;
while((line = reader.readLine()) != null) {
String[] str = line.split(";");
line = null;
switch (str[0]) {
case "insert" : //ret = SQLOptions.insert(str[1], str[2]);
System.out.println(str[1]);
break;
}
writer.print(ret);
writer.flush();
// As far as i can see it gets stuck at the end of this while, but I don't know why.
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Server {
private static final int PORT = 39165;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT);) {
System.out.println("Servidor online");
ExecutorService service = Executors.newFixedThreadPool(10);
while (true) {
Socket client = server.accept();
InetAddress ip = client.getInetAddress();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Date time = new Date();
System.out.print(sdf.format(time));
System.out.println(" " + ip + " connected");
InputStream inStream = client.getInputStream();
OutputStream outStream = client.getOutputStream();
service.execute(new ActiveServer(inStream,outStream));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
And here goes the client code:
public class Telnet {
static Console console = System.console();
public static void connect(String ip, String port) {
try(Socket socket = new Socket(ip, Integer.parseInt(port));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
String msg = null;
while(true) {
msg = console.readLine();
writer.println(msg);
writer.flush();
if (msg.equals(".quit")) {
System.out.println("Exiting...");
break;
}
String input = reader.readLine();
System.out.println(input);
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
if(args.length < 2) {
err.println("Telnet <ip> <port>");
return;
}
if (console == null) {
err.println("A console is not available");
return;
}
connect(args[0], args[1]);
}
}
On the server side, you write the response without a terminating newline:
writer.print(ret);
But on the client side, you read until the end of line:
String input = reader.readLine();
The documentation for BufferedReader#readLine says:
Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
Thus, the client will wait forever for the newline sequence which the server will never send.
I’m trying to socket program in Java. Here the client sends a string which should be reversed by the server and sent back to the client. The server is a multithreaded server. Here is the client-side code:
import java.io.*;
import java.net.*;
class ClientSystem
{
public static void main(String[] args)
{
String hostname = "127.0.0.1";
int port = 1234;
Socket clientsocket = null;
DataOutputStream output =null;
BufferedReader input = null;
try
{
clientsocket = new Socket(hostname,port);
output = new DataOutputStream(clientsocket.getOutputStream());
input = new BufferedReader(new InputStreamReader(clientsocket.getInputStream()));
}
catch(Exception e)
{
System.out.println("Error occured"+e);
}
try
{
while(true)
{
System.out.println("Enter input string ('exit' to terminate connection): ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inputstring = br.readLine();
output.writeBytes(inputstring+"\n");
//int n = Integer.parseInt(inputstring);
if(inputstring.equals("exit"))
break;
String response = input.readLine();
System.out.println("Reversed string is: "+response);
output.close();
input.close();
clientsocket.close();
}
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
}
}
Here is the server side code:
import java.io.*;
import java.net.*;
public class ServerSystem
{
ServerSocket server = null;
Socket clientsocket = null;
int numOfConnections = 0, port;
public ServerSystem(int port)
{
this.port = port;
}
public static void main(String[] args)
{
int port = 1234;
ServerSystem ss = new ServerSystem(port);
ss.startServer();
}
public void startServer()
{
try
{
server = new ServerSocket(port);
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
System.out.println("Server has started. Ready to accept connections.");
while(true)
{
try
{
clientsocket = server.accept();
numOfConnections++;
ServerConnection sc = new ServerConnection(clientsocket, numOfConnections, this);
new Thread(sc).start();
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
}
}
public void stopServer()
{
System.out.println("Terminating connection");
System.exit(0);
}
}
class ServerConnection extends Thread
{
BufferedReader br;
PrintStream ps;
Socket clientsocket;
int id;
ServerSystem ss;
public ServerConnection(Socket clientsocket, int numOfConnections, ServerSystem ss)
{
this.clientsocket = clientsocket;
id = numOfConnections;
this.ss = ss;
System.out.println("Connection "+id+" established with "+clientsocket);
try
{
br = new BufferedReader(new InputStreamReader(clientsocket.getInputStream()));
ps = new PrintStream(clientsocket.getOutputStream());
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
}
public void run()
{
String line, reversedstring = "";
try
{
boolean stopserver = false;
while(true)
{
line = br.readLine();
System.out.println("Received string: "+line+" from connection "+id);
//long n = Long.parseLong(line.trim());
if(line.equals("exit"))
{
stopserver = true;
break;
}
else
{
int len = line.length();
for (int i=len-1; i>=0; i--)
reversedstring = reversedstring + line.charAt(i);
ps.println(""+reversedstring);
}
}
System.out.println("Connection "+id+" is closed.");
br.close();
ps.close();
clientsocket.close();
if(stopserver)
ss.stopServer();
}
catch(Exception e)
{
System.out.println("Error occured."+e);
}
}
}
I get a java.lang.NullPointerException on the server side code when I enter the string and when i try to re-enter the string I get a java.net.SocketException: Socket closed exception.
Client side output:
Enter input string ('exit' to terminate connection):
usa
Reversed string is: asu
Enter input string ('exit' to terminate connection):
usa
Error occured.java.net.SocketException: Socket closed
Server side output:
Server has started. Ready to accept connections.
Connection 1 established with Socket[addr=/127.0.0.1,port=3272,localport=1234]
Received string: usa from connection 1
Received string: null from connection 1
Error occured.java.lang.NullPointerException
I tried a lot but I don't get from where I get these exceptions.
These 3 lines are the culprits in the client code:
output.close();
input.close();
clientsocket.close();
Put them outside of the while loop, and in the finally block:
try {
while(true) {
// client code here
}
} catch (Exception e) {
e.printStackTrace(); // notice this line. Will save you a lot of time!
} finally {
output.close(); //close resources here!
input.close();
clientsocket.close();
}
The issue is that as it was originally, you closed every resource, but in the next iteration, you wanted to use them agai, without initialising them...
Sidenote
Properly handling exceptions including proper logging of them. Always use either a logging framework like log4j
LOG.error("Unexpected error when deionizing the flux capacitor",e);
, or the printStackTrace() method
e.printStackTrace();
And don't forget to include the line numbers in your code, if you post a stacktrace....
EDIT
For the reversed issue:
else
{
int len = line.length();
reversedString=""; //this line erases the previous content of the reversed string
for (int i=len-1; i>=0; i--) { //always use brackets!!!
reversedstring = reversedstring + line.charAt(i);
}
ps.println(""+reversedstring);
}
What happened? The reversedString just grew and grew with each iteration, without getting erased... This is why I like to declare my variables in just the most strict scope I need them.
EDIT
To make the exit command no tkill the server, this can be one (very simple) solution:
In the ServerConnection class:
while(true)
{
line = br.readLine();
System.out.println("Received string: "+line+" from connection "+id);
if(line.equals("exit"))
{
break; //just stop this connection, don't kill server
}
else if(line.equals("stop"))
{
stopserver = true; //stop server too
break;
}
else
{
int len = line.length();
for (int i=len-1; i>=0; i--) {
reversedstring = reversedstring + line.charAt(i);
}
ps.println(""+reversedstring);
}
}
What is happening here? There is a new "command" stop, which makes the server stop, and the exit just exits the client, but does not stop the server itself...
in the 1st run of the loop you are closing all the connections which is causing the issue.
output.close();
input.close();
clientsocket.close();,move it down
Your server is calling br.readLine(); It will wait until the client sends it, but once you send a String you call:
output.close();
input.close();
clientsocket.close();
That will release the resource and result in br.readLine() being null
if (line.equals("exit")) { Here line is null, therefore you cannot call equals.
if ("exit".equals(line)) { You can change it like this to prevent that exception here.
Move the close statements to a finally block, even in the server should, if you have an exception in the while, the close are never reached, that may cause memory leaks.
Client:
} finally {
output.close();
input.close();
clientsocket.close();
}
Server:
} finally {
br.close();
ps.close();
clientsocket.close();
}
Note: you can validate them before closing to ensure they are not null.
You may have to provide a case for the input being null anyway, either exit the loop, usually you would use something like this:
if (null==line || "exit".equals(line)) {
If the client sends a null, something is wrong.
I am very new to sockets and was hoping someone could help me. I had something working but it was not sending information very quickly so i have refactored and now cannot get back to anything which works. The issue seems to be that only the first message that is published is read and then the receiver sits on client = listener.accept(); even though im pretty sure the sender is still sending messages
Can anyone see what i might be doing wrong here please?
Thanks
public class Sender {
Socket server = null;
DataInputStream inp = null;
PrintStream outp = null;
public Sender(){
server = new Socket("127.0.0.1" , 3456);
outp = new PrintStream(server.getOutputStream());
}
private void connectAndSendToServer(String message) {
outp = new PrintStream(server.getOutputStream());
outp.print(message + "\n");
outp.flush();
}
}
Receiver class
public class Receive{
public String receiveMessage(int port) {
String message= null;
ServerSocket listener = null;
Socket client = null;
try{
listener = new ServerSocket(port);
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
return br.readLine();
}
...
finally{
try {
if(client!=null && listener!=null){
client.close();
listener.close();
}
}
catch (IOException e) {
}
}
return message;
}
}
This because a ServerSocket is used as an entry point for a normal Socket. accept() is a blocking operation that is usually done on a different thread compared to the one that receives/sends data to normal Socket. It sits there and waits for a new connection to spawn a new Socket which is then used for data.
This means that while receiving messages you should call just readLine() to read from the specific Socket. Having an accept inside the receiveMessage is wrong just because it's a different operation and it's even blocking.
Socket socket = serverSocket.accept();
ClientThread thread = new ClientThread(socket);
class ClientThread extends Thread {
Socket socket;
public void run() {
while (!closed) {
String line = reader.readLine();
...
}
}
You don't need to have a thread for every client though, but you need at least two for sure if you want to make your server accept a number of connections greater than 1.
You are not using ServerSocket correctly. You shouldn't create a new instance for every message but use it as a data member maybe and run an infinite loop to get a new client socket connection. Because you create it locally, the socket is closed since the object is no longer used and referenced (and so GC'ed), when you return from the method.
Something like (< condition met > is pseudo-code defines your condition to accept new connections):
while(< condition met >) {
try {
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
String str = br.readLine();
//do something with str
} finally {
//close client socket
}
}
Better approach will be to handle client socket in a different thread so the main thread is back to accept while you can do anything with the client socket in parallel.
Try this basic Chatting Server written by me. This server simply keeps running in loop and broadcast the message send by the clients to all the other clients associated with this server.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
// ///----------------------------------------Instance Variable Fields
ServerSocket ss = null;
Socket incoming = null;
// ///----------------------------------------Instance Variable Fields
// ///---------------------------------------- static Variable Fields
public static ArrayList<Socket> socList = new ArrayList<Socket>();
// ///---------------------------------------- static Variable Fields
public void go() {
try {
ss = new ServerSocket(25005);
while (true) {
incoming = ss.accept();
socList.add(incoming);
System.out.println("Incoming: " + incoming);
new Thread(new ClientHandleKaro(incoming)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandleKaro implements Runnable {
InputStream is = null;
OutputStream os = null;
InputStreamReader isr = null;
BufferedReader br = null;
PrintWriter pw = null;
boolean isDone = false;
Socket sInThread = null;
public ClientHandleKaro(Socket sxxx) {
this.sInThread = sxxx;
}
#Override
public void run() {
if (sInThread.isConnected()) {
System.out.println("Welcamu Clienta");
System.out.println(socList);
}
try {
is = sInThread.getInputStream();
System.out.println("IS: " + is);
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
os = sInThread.getOutputStream();
pw = new PrintWriter(os, true);
String s = new String();
while ((!isDone) && (s = br.readLine()) != null) {
String[] asx = s.split("-");
System.out.println("On Console: " + s);
// pw.println(s);
Thread tx = new Thread(new ReplyKaroToClient(s,
this.sInThread));
tx.start();
if (asx[1].trim().equalsIgnoreCase("BYE")) {
System.out.println("I am inside Bye");
isDone = true;
}
}
} catch (IOException e) {
System.out.println("Thanks for Chatting.....");
} finally {
try {
Thread tiku = new Thread(new ByeByeKarDo(sInThread));
tiku.start();
try {
tiku.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Accha to hum Chalte hain !!!");
System.out.println(socList);
br.close();
pw.close();
sInThread.close();
} catch (IOException e) {
}
}
}
}
class ReplyKaroToClient implements Runnable {
public String mString;
public Socket mSocket;
public ReplyKaroToClient(String s, Socket sIn) {
this.mString = s;
this.mSocket = sIn;
}
#Override
public void run() {
for (Socket sRaW : socList) {
if (mSocket.equals(sRaW)) {
System.out.println("Mai same hun");
continue;
} else {
try {
new PrintWriter(sRaW.getOutputStream(), true)
.println(mString);
} catch (IOException e) {
System.out.println("Its in Catch");
}
}
}
}
}
class ByeByeKarDo implements Runnable {
Socket inCom;
public ByeByeKarDo(Socket si) {
this.inCom = si;
}
#Override
public void run() {
try {
new PrintWriter(inCom.getOutputStream(), true)
.println("You have Logged Out of Server... Thanks for your Visit");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server().go();
}
}