Java Multi-threaded client/server with send/receive - java

I'd like to make a client that sends strings to a server occasionally, for example: when application closed it sends a message to server- sendToServer("Client[" + IP + "]Closed")
I have a problem in my code :
Server :
try{
int port = 25000;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server Started and listening to the port 25000");
//Server is running always. This is done using this while(true) loop
while(true)
{
//Reading the message from the client
socket = serverSocket.accept();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String received = br.readLine();
System.out.println("Message received from client is "+received);
//Multiplying the number by 2 and forming the return message
String returnMessage;
try
{
returnMessage = "You send : " + received;
}
catch(NumberFormatException e)
{
//Input was not a number. Sending proper message back to client.
returnMessage = "Please send a proper number\n";
}
//Sending the response back to the client.
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
System.out.println("Message sent to the client is "+returnMessage);
bw.flush();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
socket.close();
}
catch(Exception e){
}
}
CLIENT :
try {
String host = IP;
int port = Port;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String number = "2";
String sendMessage = number + "\n";
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+sendMessage);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " +message);
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
//Closing the socket
try
{
socket.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}

Related

ServerSocket close method not releasing port

I am working on 2 applications (web and standalone apps). I have built functionality into the web app for users to be able to restart certain modules of the standalone app from the web page. The way i accomplish this is using a ServerSocket object that listens on a port that is configured as a parameter in the database. This is a shortened version of the server side that listens for the incoming requests :
try
{
int port = Integer.parseInt(globalParamService.findByName("serviceInterconnectPort").getValue());
ServerSocket serverSocket = new ServerSocket(port);
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully started web client connector on port " + port);
while(running)
{
socket = serverSocket.accept();
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Incoming request from web client");
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
if (message.contains("Restart Web Client Connector"))
{
if (!main.isWebClientConnectorRestarting())
{
main.restartWebClientConnector();
String returnMessage = "Done\n";
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
bw.flush();
os.close();
osw.close();
bw.close();
}
else
{
String returnMessage = "Request cancelled\n";
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
bw.flush();
os.close();
osw.close();
bw.close();
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Web client connector restart request cancelled, restart already in progress");
}
}
is.close();
isr.close();
br.close();
socket.close();
}
}
catch (Exception ex)
{
logEntryService.logError(LogEntry.CONNECTIVITY, "Error processing restart request from web client : " + ex.getMessage());
}
Upon deployment of my 2 apps, it is possible that the users would need to change the port this listener is running on. When they do change it from the web app, i extract the unchanged port before updating it in the DB and send it to the below method :
public void restartWebClientConnector(int oldPort)
{
Thread t = new Thread(() ->
{
try
{
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Connecting to port " + oldPort + " to restart web client connector");
InetAddress address = InetAddress.getByName("localhost");
socket = new Socket(address, oldPort);
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Successfully connected to port " + oldPort);
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("Restart Web Client Connector\n");
bw.flush();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
if (message.compareTo("Done") == 0)
{
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Web client connector restart request acknowledged");
}
else
{
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Web client connector restart request cancelled, restart already in progress");
}
os.close();
osw.close();
bw.close();
is.close();
isr.close();
br.close();
socket.close();
}
catch (IOException | NumberFormatException ex)
{
logEntryService.logError(LogEntry.CONNECTIVITY, "Error sending web client connector restart command : " + ex.getMessage());
}
});
t.start();
}
This method then calls the following code which terminates my listener thread and re initializes it on the new updated port number :
public void restartWebClientConnector()
{
if (!webClientConnectorRestarting)
{
webClientConnectorRestarting = true;
webClientConnector.setRunning(false);
webClientConnectorThread.interrupt();
initWebClientConnector();
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully restarted web client connector");
webClientConnectorRestarting = false;
}
}
private void initWebClientConnector()
{
logEntryService.logInfo(LogEntry.CORE, "Initializing web connector");
try
{
webClientConnector = new WebClientConnector(this, globalParamService, logEntryService);
webClientConnectorThread = new Thread(threads, webClientConnector);
webClientConnectorThread.setName("Web Client Connector Thread");
webClientConnectorThread.start();
}
catch (Exception ex)
{
logEntryService.logError(LogEntry.CORE, "Error initializing messaging process : " + ex.getMessage());
}
}
Everything works great except one thing : the old port number is NOT freed up despite explicitly closing everything i can think of. When doing netstat -a after changing the port from the web client, the old port is still listed in LISTENING status. I can change it several times in a row and it works every time but the ports are not freed up. I have spent quite some time researching this and from what i've read it appears i am doing everything correctly (evidently not!).
Whatever input you guys may have would be helpful.
Cheers!
I would recommend you to use resource try blocks, or at least try-finally blocks to ensure the resources are closed:
int port = Integer.parseInt(globalParamService.findByName("serviceInterconnectPort").getValue());
try (ServerSocket serverSocket = new ServerSocket(port)) {
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully started web client connector on port " + port);
while (running) {
try (Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr)) {
String message = br.readLine();
if (message.contains("Restart Web Client Connector")) {
if (!main.isWebClientConnectorRestarting()) {
main.restartWebClientConnector();
String returnMessage = "Done\n";
try (OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw)) {
bw.write(returnMessage);
bw.flush();
}
} else {
String returnMessage = "Request cancelled\n";
try (OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw)) {
bw.write(returnMessage);
bw.flush();
}
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Web client connector restart request cancelled, restart already in progress");
}
}
}
}
} catch (IOException ex) {
logEntryService.logError(LogEntry.CONNECTIVITY, "Error processing restart request from web client : " + ex.getMessage());
}
I changed my WebClientConnector class' run method (it implements Runnable) to the below code :
#Override
public void run()
{
try
{
initWebClientListener();
}
finally
{
try
{
serverSocket.close();
}
catch (IOException ex1)
{}
}
}
And changed my restart method to call interrupt on it as well as setting the running variable to false. The ServerSocket now closes properly and the port is freed.

Socket Java - Client receives a wrong information

I am trying to send two numbers via Socket. The Server receive the numbers and I make some calculation, but when I send back to Client the result, the Client receive a number which he send it.
Where I doing wrong beceause I don't understand?
Client.java
public class Client {
private static Socket socket;
public static void main(String args[]) {
try {
String host = "localhost";
int port = 25010;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String number = "2";
String number2 = "5";
String sendMessage = number + "\n";
String sendMessage2 = number2 + "\n";
bw.write(sendMessage);
bw.write(sendMessage2);
bw.flush();
System.out.println("Message sent to the server:\n" + sendMessage + sendMessage2);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " + message);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
//Closing the socket
try {
socket.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
Server.java
public class Server {
private static Socket socket;
public static void main(String[] args) {
try {
int port = 25010;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server Started and listening to the port " + port);
ArrayList<String> arr = new ArrayList<String>();
//Server is running always. This is done using this while(true) loop
while(true) {
//Reading the message from the client
socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); // primeste mesaj de la client
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); // transmite raspuns catre client
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String inputLine;
while ((inputLine = br.readLine()) != null) {
out.println(inputLine);
arr.add(inputLine.trim());
}
System.out.println("Message received from client is:");
for (int i = 0; i < arr.size(); i++) {
System.out.println(arr.get(i));
}
//Return message
String returnMessage = null;
try {
int numberInIntFormat = 0;
int num = 1;
for (int i = 0; i < arr.size(); i++) {
System.out.println(arr.get(i));
numberInIntFormat = Integer.parseInt(arr.get(i));
num = num * numberInIntFormat;
}
arr.clear();
returnMessage = String.valueOf(num);
} catch(NumberFormatException e) {
//Input was not a number. Sending proper message back to client.
returnMessage = "Please send a proper number\n";
}
//Sending the response back to the client.
bw.write(returnMessage);
bw.flush();
System.out.println("returnMessage = " + returnMessage);
System.out.println("Message sent to the client is "+ returnMessage);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch(Exception e) {}
}
}
}
Your server code echoes everything it reads from the client back to the client before it does anything else with it:
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); // primeste mesaj de la client
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); // transmite raspuns catre client
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String inputLine;
while ((inputLine = br.readLine()) != null) {
out.println(inputLine); // <-- HERE
arr.add(inputLine.trim());
}
It is unsurprising that the client receives what the server sent.
Try this:
Client:
public class Client {
private static Socket socket;
public static void main(String args[]) {
try {
String host = "localhost";
int port = 25010;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String number = "2";
String number2 = "5";
String sendMessage = number + "\n";
String sendMessage2 = number2 + "\n";
bw.write(sendMessage);
bw.write(sendMessage2);
bw.newLine(); // You need to send a special line for say to the server: "Hey, I have done";
bw.flush();
System.out.println("Message sent to the server:\n" + sendMessage + sendMessage2);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " + message);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
//Closing the socket
try {
socket.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
Server:
public class Server {
private static Socket socket;
public static void main(String[] args) {
try {
int port = 25010;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server Started and listening to the port " + port);
ArrayList<String> arr = new ArrayList<String>();
//Server is running always. This is done using this while(true) loop
while(true) {
//Reading the message from the client
socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); // primeste mesaj de la client
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); // transmite raspuns catre client
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String inputLine;
while ((inputLine = br.readLine()) != null && inputLine.length() > 0) { // You need to stop loop when you get empty line
// out.println(inputLine);
arr.add(inputLine.trim());
System.out.println("Message received from client is:"+inputLine.trim());
}
System.out.println("Message received from client is:");
//Return message
String returnMessage = null;
try {
int numberInIntFormat = 0;
int num = 1;
for (int i = 0; i < arr.size(); i++) {
System.out.println(arr.get(i));
numberInIntFormat = Integer.parseInt(arr.get(i));
num = num * numberInIntFormat;
}
arr.clear();
returnMessage = String.valueOf(num);
} catch(NumberFormatException e) {
//Input was not a number. Sending proper message back to client.
returnMessage = "Please send a proper number\n";
}
//Sending the response back to the client.
bw.write(returnMessage+"\n"); // You need to add '\n' otherwise readLine never gets;
bw.flush();
System.out.println("returnMessage = " + returnMessage);
System.out.println("Message sent to the client is "+ returnMessage);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch(Exception e) {}
}
}
}
String inputLine;
while ((inputLine = br.readLine()) != null) {
arr.add(inputLine.trim());
}
With this change, the output is:
Server:
Server Started and listening to the port 25010
Client:
Message sent to the server:
2
5
And now the Server is 'blocked' in while loop and the Client don't recive any feedback.
I found a better method:
while (br.ready() && (inputLine = br.readLine()) != null)
This tell that to read the buffer if it is something to read.
With the response from #John Bollinger, the buffer read only up to first line break, so if you try to parse a String which contains a line break, you will get out when appear the line break.
With br.ready() it will parse all the String and will get out at the end of buffer.

Java Client/Server App will not readLine()

I am trying to write a program that allows the user to send a message to a server and receive a modified version of that message. For some reason, the flow of the program stops on a certain line below, which I have pointed out. Can anybody explain why this isn't working? Thanks.
Server Side
import java.net.*;
import java.io.*;
public class Server{
public final static int port = 1025;
public static void main (String[] args){
ServerSocket serverSocket;
Socket client;
PrintWriter output;
try{
serverSocket = new ServerSocket(port);
try{
while(true){
client = serverSocket.accept();
InputStream is = client.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from client is " + message);
String returnMessage = message + message;
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
System.out.println("Message sent to the client is " + returnMessage);
bw.flush();
}
} catch(IOException e){
serverSocket.close();
System.err.println(e);
}
} catch(IOException e){
System.err.println(e);
}
}
}
Client Side
import java.util.Scanner;
import java.net.*;
import java.io.*;
class Client{
public void getService(String destination, int port){
try{
while(true)
{
Scanner in = new Scanner(System.in);
System.out.println("Send a message to the server: ");
String message = in.nextLine();
Socket server = new Socket(destination, port);
OutputStream os = server.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String sendMessage = message + "\n";
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+ sendMessage);
InputStream is = server.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message2 = br.readLine(); // I have determined that the program's flow proceeds no further than this line
System.out.println("Message received from the server : " + message2);
}
} catch(IOException e){
e.printStackTrace();
}
}
public static void main(String[] args){
String serverAddress = args[0];
System.out.println(serverAddress);
Client client = new Client();
client.getService(serverAddress, 1025);
}
}
The server uses a BufferedReader, whose readLine method requires an end of line delimiter, but the Client is not sending it - rather, it reads the line (with end of line delimiter stripped) and attempts to echo this message. Append a new line character to the data sent by the client so that the readLine method of the Server does not block while waiting for the line:
String returnMessage = message + message + "\n";

Why is the message never delivered?

For some reason, i never get the message back from the server to the client :/ whats happening? how can i know or solve this?
I send the request from the client, the server gets that request, process it and generate a response that is send. But the client never reads it.
public class Client {
private static Socket socket;
public static void main(String args[]) {
try {
String host = "localhost";
int port = 13579;
System.out.println("Conecting to : " + host + ":" + port);
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String sendMessage = "103700635105281047295162150000001418 99900001000000717999000NovoTransactionsBusiness 717 VE000000000054300052810472900000000000099900001 1803\n";
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : " + sendMessage);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
//But i never get the message back
String message = br.readLine();
System.out.println("Message received from the server : " + message);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
//Closing the socket
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
The server is running fine!
public class Server {
private static Socket socket;
public static void main(String[] args) {
try {
int port = 13579;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Servidor Iniciado escuchando al puerto " + port);
while (true) {
socket = serverSocket.accept();
String strRequest = new BufferedReader(new InputStreamReader(socket.getInputStream())).readLine();
System.out.println("Request Received: " + strRequest);
String returnMessage;
try {
returnMessage = new NovoTrans().init(strRequest).toString();
} catch (Exception e) {
returnMessage = "Error: " + e.getMessage() + "\n";
}
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(returnMessage);
System.out.println("Sending Message: " + returnMessage);
bw.flush();
}
} catch (Exception e) {
} finally {
try {
socket.close();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
}
I suggest you to use PrintWriter instead of BufferedWriter. There is no need to call flush after each line and simply use println() method along with auto-flush feature to add a new line as well.
Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output.
These methods use the platform's own notion of line separator rather than the newline character.
There is no need to append \n in the message itself.
Sample code: (Do the changes in both server and client side classes)
// here true means auto flush when `println()` method is called
PrintWriter bw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
bw.println(returnMessage);

tcp connection stuck in close_wait java

There are lot of close_wait connection, when ever a client client sends the message to the server and comes out the TCP FSM stuck in the CLOSE_WAIT STATE
This the Client code,
public class Client1
{
private static Socket socket;
public static void main(String args[])
{
try
{
String host = "localhost";
int port = 25000;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String number = "2";
String sendMessage = number + "\n";
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+sendMessage);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " +message);
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
//Closing the socket
try
{
socket.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
This the Server code which listen to the upcoming connection
public class Server1
{
private static Socket socket;
public static void main(String[] args)
{
try
{
int port = 25000;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server Started and listening to the port 25000");
//Server is running always. This is done using this while(true) loop
while(true)
{
//Reading the message from the client
socket = serverSocket.accept();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String number = br.readLine();
System.out.println("Message received from client is "+number);
//Multiplying the number by 2 and forming the return message
String returnMessage;
try
{
int numberInIntFormat = Integer.parseInt(number);
int returnValue = numberInIntFormat*2;
returnMessage = String.valueOf(returnValue) + "\n";
}
catch(NumberFormatException e)
{
//Input was not a number. Sending proper message back to client.
returnMessage = "Please send a proper number\n";
}
//Sending the response back to the client.
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
System.out.println("Message sent to the client is "+returnMessage);
bw.flush();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
socket.close();
}
catch(Exception e){}
}
}
}
The output TCP FSM
-bash:~$ netstat -an | grep 25000
tcp4 0 0 127.0.0.1.25000 127.0.0.1.56459 CLOSE_WAIT
tcp46 0 0 *.25000 *.* LISTEN
You're closing the accepted socket in the wrong place. It needs to be inside the accept loop.

Categories

Resources