java.lang.NullPointerException and java.net.SocketException - java

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.

Related

Java - Getting error "Socket is closed" when my Client class connects on my Server class

I made two classes in Java named Server.java and Client.java. The Server is listening to a port and is waiting for a Client to connect (using sockets). When the client connects he can type a pair of numbers separated by "space" and if that pair exists in my edge_list.txt file the Server returns "1" to the client, if not it returns "0". After I completed my initial project I wanted to also use Threads so that it can handle multiple users at once, but when the Client connects I get -> java.net.SocketException: Socket is closed.
I reviewed my code and try using flush() instead of close(). Also, I thought I was closing the socket before the user can read the file, but it didn't seem that was the case. Below I will have the Server.java code block and not the Client.java, cause it doesn't seem to be the problem.
Server.java
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
private static final int PORT = 9999;
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("Server is listening on port " + PORT);
while (true) {
try (Socket socket = serverSocket.accept()) {
System.out.println("Client connected: " + socket);
new ClientHandler(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static class ClientHandler extends Thread {
private Socket socket;
ClientHandler(Socket socket){
this.socket = socket;
}
#Override
public void run() {
try {
//Creating Sockets and Streams
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output));
while (socket.isConnected() && !socket.isClosed()) {
//Reading what the Client types
String request = reader.readLine();
//Split the values with "space" and store them in an array,
//then parse those values to two integers
String[] values = request.split(" ");
int A = Integer.parseInt(values[0]);
int B = Integer.parseInt(values[1]);
//Check if the pair in the file exists using checkPairInFile() method
boolean exists = checkPairInFile(A, B);
//if it does print 1 else 0
writer.println(exists ? "1" : "0");
//Flush the output to send the response back to the client
writer.flush();
}
//Print the disconnected user
System.out.println("Client disconnected: " + socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static boolean checkPairInFile(int A, int B) {
try (Scanner scanner = new Scanner(new File("edge_list.txt"))) {
//Scanning the file lines
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
//Split the values with "space"
String[] values = line.split(" ");
//Parse the values from String -> Int
int a = Integer.parseInt(values[0]);
int b = Integer.parseInt(values[1]);
//if both exist return true
if (A == a && B == b) {
return true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
}
P.S. Thanks in advance for your help, in case this is problem with my Client.java file I will update the post.
This part:
try (Socket socket = serverSocket.accept()) {
System.out.println("Client connected: " + socket);
new ClientHandler(socket).start();
}
accepts a socket, then prints a message, then starts a new thread, then closes the socket. At some point later the new thread finishes starting up and tries to use the socket and realizes it was already closed.
try (...) {...} (officially called try-with-resources) always closes the things when it gets to the }. That's the point of it. If you don't want to close the socket at the } then you shouldn't use this type of statement.

Java Socket Read Input Twice

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!

Java Simple Client Server application

Im sorry I am coding 12 hours now and now I have a "brainlag".
I made a little Client Server programm.
Client:
public void send(String send) {
DataOutputStream out;
Socket client;
try {
client = new Socket("192.168.0.138", port);
out = new DataOutputStream(client.getOutputStream());
out.writeChars(send + '\n');
Thread.sleep(100L);
} catch (IOException ex) {
System.err.println("Can't connect to Server!");
} catch (InterruptedException ex) {
System.err.println("Cant sleep!");
}
}
Server:
public static void main(String[] args) throws IOException {
int port = 5000;
String cIn;
System.out.println("Running on Port 5000");
ServerSocket sock = new ServerSocket(port);
Socket client;
BufferedReader inFromClient;
while (true) {
client = sock.accept();
inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
cIn = inFromClient.readLine();
System.out.println("" + cln);
}
}
Now my question. How can i make it that my string (data) is sending in a loop to the server while I input a new data.
If a make a normal while loop, my string is sending permanently to the server. If i change my String it doesn't matter.
I would make it that if i change my String, that the new String is sending to the server.
I'm sorry for my bad english. I hope you will understand.
how about sending the data with a new thread whichs sends the data in a loop. when you input some new data interupt the old thread and start a new one and so on?
I think you need to add a bufferedReader close at the end of the while loop.
while (true) {
client = sock.accept();
inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
cIn = inFromClient.readLine();
System.out.println("" + cln);
inFromClient.close() //add this
}
If I resume:
- you need a console app (or window/awt/swing ...) or main client app which take a String, and sometimes change this String.
- this String must be sent by your function "send", continuously, with the last String
I propose you:
1 - to fix the loop (1 sec, 2, sec, x seconds ?)
2 - to use a share variable (in critical section, or synchronized), your main client app writes it, and changes it when you want, and your "send" function read it every x seconds and sends it.
Your client could look like that:
// SHARED VARIABLE
static String warning="";
final static Object warning_sync=new Object();
// Alert function
class Thread_alert extends Thread
{
// YOUR CODE
public void send(String send) {
DataOutputStream out;
Socket client;
int port=80;
try {
client = new Socket("192.168.0.138", port);
out = new DataOutputStream(client.getOutputStream());
out.writeChars(send + '\n');
Thread.sleep(100L);
} catch (IOException ex) {
System.err.println("Can't connect to Server!");
} catch (InterruptedException ex) {
System.err.println("Cant sleep!");
}
}
public Thread_alert()
{
super();
}
public void run()
{
while (true)
{
// WHAT YOU HAVE TO DO
synchronized(warning_sync)
{
System.err.println("WARN: "+warning);
send(warning);
}
// Sleep 5 seconds
try {
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
// while (true)
}
// public void run()
}
// class Thread_alert
public void console_client ()
{
// START THE THREAD
Thread_alert lethread=new Thread_alert();
lethread.start();
// INPUT LOOP
Scanner s = new Scanner(System.in);
String line;
while ((line=s.nextLine())!=null)
{
System.out.println("STRING:'"+line+"'");
// Fix the warning
synchronized(warning_sync)
{
warning=line;
}
// bonus
// IF STOP: STOP
if (warning.equals("STOP"))
{
lethread.stop();
break;
}
}
// while ((line=s.nextLine())!=null)
// safe
s.close();
}

the ReadLine doesnt wait for input

I have a socket client sending text to a socket server but the ReadLine doesnt seem to wait to receive a line before proceeding. Here is the of the server receiving the text:
public void run() {
try {
serveurSocket = new ServerSocket(PORT_ID);
connexionSocket = serveurSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(connexionSocket.getInputStream()));
PrintWriter writer = new PrintWriter(connexionSocket.getOutputStream(), true);
messageRecu = "";
while (true) {
messageRecu = reader.readLine();
messageRecu = messageRecu.toUpperCase();
writer.println(messageRecu);
}
//reader.close();
//writer.close();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
After establishing the socket between client and server, the execution halts at reader.readLine until I send manually a string thru the socket. Which is normal and wanted. Codes resumes and its fine until its loops back to reader.ReadLine() where it will read a "null" line instead of waiting for input from the socket like it did the first time... this will obviously mess up the next command to uppercase. So how can I fix this?
EDIT: I'll add the client side if that can help understand.
public class ClientSocket {
private Socket clientSocket;
public boolean isClosed() { return clientSocket.isClosed(); }
public boolean connectToSocket (String ip, int port) {
try {
clientSocket = new Socket(ip, port);
return true;
}
catch (IOException e) {
System.out.println(e);
return false;
}
}
public String sendToServer(String messageClient) {
String messageRecu = "";
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true);
writer.println(messageClient);
messageRecu = reader.readLine();
reader.close();
writer.close();
return messageRecu;
}
catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
return messageRecu;
}
}
}
A button press will call "connectTosocket" to initiate the socket. A second button when pressed will send the content of a textfield using "sendToServer".
Server does receive the message and return it capitalized but I wish for the socket to remain open with the server and if I send an other string for the same sequence to happen. Not even sure it can be done :(
According to the documentation of BufferedReader#readLine, a null is returned if the end of stream has been reached.
Change your reading loop to :
while ((messageRecu = reader.readLine()) != null) {
messageRecu = messageRecu.toUpperCase();
writer.println(messageRecu);
}
//Get out of the loop when the end of stream is reached.
As per Reading from and Writing to a Socket chapter of the Java tutorial.
As a side note, while(true) loops are not really appreciated.
The "null" signals for end of connection from the client side - which is why the connection disconnects. If you want to support multiple requests, you should run a new ServerSocket.accept() each time and wait for a new client to connect.
KKMultiServer class:
import java.net.*;
import java.io.*;
public class KKMultiServer {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java KKMultiServer <port number>");
System.exit(1);
}
int portNumber = Integer.parseInt(args[0]);
boolean listening = true;
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
while (listening) {
new KKMultiServerThread(serverSocket.accept()).start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " + portNumber);
System.exit(-1);
}
}
}
KKMultiServerThread class:
import java.net.*;
import java.io.*;
public class KKMultiServerThread extends Thread {
private Socket socket = null;
public KKMultiServerThread(Socket socket) {
super("KKMultiServerThread");
this.socket = socket;
}
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
) {
String inputLine, outputLine;
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye"))
break;
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You can read more about sockets in Oracle tutorials

Server not receiving in socket communication

I'm trying to make a Java program in which the server generates a random number and, after establishing a connection with a client, lets it guess the number. However, they both don't seem able to receive each others' messages.
Server side:
package numberguessserv;
import java.net.*;
import java.io.*;
import java.util.Random;
import java.util.Scanner;
public class NumberGuessServ {
public static void main(String[] args) {
Scanner inpkb = new Scanner(System.in);
Random randomGenerator = new Random();
int randomNum = randomGenerator.nextInt(10);
String number = Integer.toString(randomNum);
int port;
boolean isGuessed = false;
String msgReceived;
Socket connect = new Socket();
System.out.print("port: ");
port = inpkb.nextInt();
try {
ServerSocket clSock = new ServerSocket(port);
System.out.println("Waiting...");
connect = clSock.accept();
System.out.println("Connection established with"+connect.getInetAddress());
InputStreamReader isr = new InputStreamReader(connect.getInputStream());
BufferedReader isrBuff = new BufferedReader(isr);
OutputStreamWriter osw = new OutputStreamWriter(connect.getOutputStream());
BufferedWriter oswBuff = new BufferedWriter(osw);
while (!isGuessed) {
msgReceived = isrBuff.readLine();
System.out.println("Number received: "+msgReceived);
if (msgReceived.equals(number)) {
isGuessed = true;
oswBuff.write("Right!");
oswBuff.flush();
}
else {
oswBuff.write("Wrong!");
oswBuff.flush();
}
if (isGuessed)
System.out.println("Number was guessed right.");
else
System.out.println("Number was guessed wrong.");
}
}
catch (Exception ex) {
System.out.println("An exception has occurred: "+ex);
}
finally {
try {
connect.close();
}
catch (Exception ex) {
System.out.println("An exception has occurred: "+ex);
}
}
}
}
Client side:
package numberguessclient;
import java.io.*;
import java.util.Scanner;
import java.net.*;
public class NumberGuessClient {
public static void main(String[] args) {
Scanner inpkb = new Scanner(System.in);
int port;
String IP;
boolean isGuessed = false;
String number, msg;
Socket serv = new Socket();
System.out.print("IP: ");
IP = inpkb.next();
System.out.print("port: ");
port = inpkb.nextInt();
try {
serv = new Socket(IP,port);
System.out.println("Connetion established with"+serv.getInetAddress());
InputStreamReader isr = new InputStreamReader(serv.getInputStream());
BufferedReader isrBuff = new BufferedReader(isr);
OutputStreamWriter osw = new OutputStreamWriter(serv.getOutputStream());
BufferedWriter oswBuff = new BufferedWriter(osw);
while (!isGuessed) {
System.out.print("number: ");
number = inpkb.next();
oswBuff.write(number);
oswBuff.flush();
System.out.println("Number sent.");
msg = isrBuff.readLine();
System.out.println("The reply was received: "+msg);
if (msg.equals("Right!")) {
isGuessed = true;
System.out.println(msg);
}
else {
System.out.println(msg+"\nTry again...");
}
}
}
catch (Exception ex) {
System.out.print("An exception has occurred: "+ex);
}
finally {
try {
serv.close();
}
catch (Exception ex) {
System.out.print("An exception has occurred: "+ex);
}
}
}
}
The readLine() waits for the end of line. Unless and until it gets a new line character, it will wait up there reading.
So, you need to give a new line characer '\n' every time you give an input to the output stream so that the readLine() reads a new line character and does not wait.
Currently in your code, you need to give a new line character everytime you are giving input by doing the following:
oswBuff.write("any message");
oswBuff.write('\n'); //add this statement everywhere you are writing to the output stream
oswBuff.flush();
This complies well for both the server as well as client.
That's expected. Both ends read using
isrBuff.readLine();
So, they both expect the other end to send a line. But none of them sends a line. They both do
oswBuff.write(number);
oswBuff.flush();
That sends some characters, but doesn send any newline character. The receiving end doesn't have any way to know that the end of line has been reached, and it thus continues blocking until it receives the EOL.

Categories

Resources