How can I get acknowledgment at client side without closing server socket? - java

I'm able to send string to the server and server also received the same. Server is able to send the acknowledgment but client is not getting acknowledged until server ends the connection. But I don't want to close the connection. How should I display the acknowledgment without closing the connection?
//This is Client
public void Actuator1_Stop(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Socket socket = new Socket("localhost", 1028);
DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
dout.writeUTF("Stop_Actuator");
dout.flush();
System.out.println("Command Sent = Stop_Actuator");
//Get the return message from server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("ACK received from the server : " +message);
socket.close();
} catch(Exception exception) {
exception.printStackTrace();
}
}
//This is Server
class Socket4 implements Runnable {
public void run() {
try {
ServerSocket ss = new ServerSocket(1028);
while(true) {
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String cmd = dis.readUTF();
System.out.println("Command= "+cmd);
//Sending the response back to the client
String ack = null;
OutputStream os = s.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
if(cmd.equals("Stop_Actuator")) {
ack= "Ok";
bw.write(ack);
} else {
ack = "Error";
bw.write(ack);
}
System.out.println("ACK sent to the client is "+ack);
bw.flush();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
public class MyServer {
public static void main(String[] args) {
Socket1 s1 = new Socket1();
Socket2 s2 = new Socket2();
Socket3 s3 = new Socket3();
Socket4 s4 = new Socket4();
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s2);
Thread t3 = new Thread(s3);
Thread t4 = new Thread(s4);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
}

How should I display the acknowledgment without closing the connection?
In your client you are doing a read-line:
String message = br.readLine();
However from the server you are not sending a complete line. You need to add line termination characters to the end of the message:
ack = "Ok\n";
bw.write(ack);
The read-line then completes and the client gets the ack. Obviously the error ack also needs a newline ("Error\n").
Make sure that you are properly closing the accepted socket and the server socket that are created in Socket4.run(). I assume that you are just posting portions of your code but make sure to close those sockets in a try/finally blocks.

Related

Unable to read data sent from socket server in java

i want to make communication between android device and java server.
Server side:
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
OutputStream out = socket.getOutputStream();
PrintStream pw = new PrintStream(out);
pw.print("hello");
pw.flush();
socket.close();
Android client side :
public class connectTask extends Thread {
#Override
public void run() {
super.run();
while (true) {
try {
Socket socket = new Socket("192.168.0.101", 4444);
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = reader.readLine();
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(line);
}
});
socket.close();
} catch (IOException e) {
}}}}
and starting thread this way:
thread = new Thread(new connectTask());
thread.start();
the problem is I cannot get anything from java server. I either send or receive data wrong and i can't figure out what's the issue, what am I doing wrong here?
Your code looks good (may be String line = ... should be final String line = ...) and IP address and port of Server need to be checked.

Java OutputStream only flushes data on close

Socket socket = new Socket("192.168.178.47", 82);
OutputStream out = socket.getOutputStream();
out.write("{ \"phone\": \"23456789\" }".getBytes());
out.flush();
//Server
InputStream in = client.getInputStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
int i = 0;
while((i = in.read()) >= 0) {
bOut.write(i);
}
String complete = new String(bOut.toByteArray(), "UTF-8");
I had tried to send data via OutputStream to a socket but the data is not flushing. If I add an out.close(); to the end then it works perfectly, but the socket is closed and I cannot accept the response. Does anybody know why? The server is not giving any type of error. I had used Java 1.7!
It is possible that the server is waiting for the end of line. If this is the case add "\n" to the text
I'm not sure of the labelling "//Server" in your question, but I'm assuming the following code is the server code:
InputStream in = client.getInputStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
int i = 0;
while((i = in.read()) >= 0) {
bOut.write(i);
}
String complete = new String(bOut.toByteArray(), "UTF-8");
This will continue to read, blocking each time, until it gets a value from read() less than zero. That only happens if the stream is closed.
It really looks like you need to establish your own protocol. So instead of looking for "<=0" look for some constant value that signals the end of the message.
Here's a quick demonstration of what I mean (I didn't have time yesterday). I have 3 classes, Message,MyClient (which also is the main class), and MyServer. Notice there isn't anything about sending or receiving a newline. Nothing is setting tcpNoDelay. But it works fine. Some other notes:
This code only sends and receives a single request and response.
It doesn't support sending multiple Message instances. That would require checking for the start of a Message as well as the end.
Message class:
public class Message {
public static final String MSG_START = "<message>";
public static final String MSG_END = "</message>";
private final String content;
public Message(String string){
content = string;
}
#Override
public String toString(){
return MSG_START + content + MSG_END;
}
}
MyServer class
public class MyServer implements Runnable{
public static final int PORT = 55555;
#Override
public void run(){
try {
ServerSocket serverSocket = new ServerSocket(PORT);
Socket socket = serverSocket.accept();
String message = getMessage(socket);
System.out.println("Server got the message: " + message);
sendResponse(socket);
}catch (IOException e){
throw new IllegalStateException(e);
}
}
private void sendResponse(Socket socket) throws IOException{
Message message = new Message("Ack");
System.out.println("Server now sending a response to the client: " + message);
OutputStream out = socket.getOutputStream();
out.write(message.toString().getBytes("UTF-8"));
}
private String getMessage(Socket socket) throws IOException{
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
StringBuilder sb = new StringBuilder(100);
byte[] bytes = new byte[1024<<8];
while(sb.lastIndexOf(Message.MSG_END) == -1){
int bytesRead = in.read(bytes);
sb.append(new String(bytes,0,bytesRead,"UTF-8"));
}
return sb.toString();
}
}
MyClient class
public class MyClient {
public static void main(String[] args){
MyClient client = new MyClient();
Thread server = new Thread(new MyServer());
server.start();
client.performCall();
}
public void performCall(){
try {
Socket socket = new Socket("127.0.0.1",MyServer.PORT);
sendMessage(socket, "Why hello there!");
System.out.println("Client got a response from the server: " + getResponse(socket));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
public String getResponse(Socket socket) throws IOException{
String response;
StringBuilder sb = new StringBuilder(100);
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
while(sb.lastIndexOf(Message.MSG_END) == -1){
int bytesRead = in.read(bytes);
sb.append(new String(bytes,0,bytesRead,"UTF-8"));
}
response = sb.toString();
return response;
}
public void sendMessage(Socket socket, String message) throws IOException{
Message msg = new Message(message);
System.out.println("Client now sending message to server: " + msg);
OutputStream out = socket.getOutputStream();
out.write(msg.toString().getBytes("UTF-8"));
}
}
The output
Client now sending message to server: Why hello there!
Server got the message: Why hello there!
Server now sending a response to the client: Ack
Client got a response from the server: Ack
Process finished with exit code 0
The problem is not that you are not flushing properly, but that the reading code waits for the socket to disconnect before handling the data:
while((i = in.read()) >= 0)
Will loop as long as something can be read from in (the socket's InputStream). The condition will not fail until the other peer disconnects.
Try using
socket.setTcpNoDelay(true);
There is buffering that occurs for performance reasons (read up on Nagle's algorithm).
Looking at your code it seems ok. However you are sending less than the MTU Nagle's algothrim could be holding it back until enough data is present for a full packet or you close the socket.
So - try this:
socket.setTCPNoDelay(true);
http://en.wikipedia.org/wiki/Nagle%27s_algorithm
https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#setTcpNoDelay-boolean-

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.

Difficulty with socket communication from Server to Client

I have a relatively simple program where I try establish Client Server connection and at the same time I use threads in the client side to allow for multiple connections.
I run the server and then the server invokes the client constructor and passes the port connection to the client and the thread is started on the client side.
The problem I have is that when I run the server side it doesn't want to go beyond the constructor call. It seems to get stuck at the constructor.
Sorry all this sounds a bit confusing
Any thoughts perhaps
this is the server side
ServerMultipleThreads()
{
System.out.println("Starting the server first...");
try
{
ServerSoc = new ServerSocket(7777);
listening = true;
}
catch(Exception e)
{
System.out.println(e.toString());
System.exit(1);
}
System.out.println("The server has started running");
while(listening)
{
try
{
//creating the client socket and starting the new client session
new ClientSession(ServerSoc.accept());
System.out.println("The clientSession was called");
in = new DataInputStream(clientSocket.getInputStream());
BufferedReader is = new BufferedReader(new InputStreamReader(in));
os = new PrintStream(clientSocket.getOutputStream());
while(true)
{
line = is.readLine();
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("myFile,txt")), true);
out.println(line);
}
}
catch(IOException ioe)
{
System.out.println(ioe.toString());
}
}
}
and this is on client side
ClientSession(Socket s)
{
clientSocket = s;
try
{
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out.println("Welcome");
}
catch(IOException exe)
{
System.out.println(exe.toString());
}
//starting the thread
while(runner == null)
{
runner = new Thread(this);
runner.start();
}
}
public void run()
{
while(runner == Thread.currentThread())
{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String stdIn;
try
{
while((stdIn = buf.readLine()) != null)
{
out.println(stdIn);
}
}
catch(IOException exe)
{
exe.toString();
}
try
{
Thread.sleep(10);
}
catch(InterruptedException e){}
}
Kind regards
Arian
That is because ServerSocket.accept() blocks until it receives a client request.
You need to have a client calling the server, something like this:
Socket socket = new Socket(host, port);
InputStream in = socket.getInputStream();
// write some data...

Server and ServerSocket in one Application: not working

I am trying to write a small program, that opens a server, creates a client that connects to this server and receives a message from it.
This is the Code so far
public static void main(String[] args) {
final ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(12345);
Thread t = new Thread(){
public void run(){
try {
Socket server = serverSocket.accept();
PrintWriter writer = new PrintWriter(server.getOutputStream(), true);
writer.write("Hello World");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t.start();
Socket client = new Socket("localhost", 12345);
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
String message = reader.readLine();
System.out.println("Received " + message);
} catch (IOException e1) {
e1.printStackTrace();
}
}
If i run program it keeps waiting in readLine() - so obviously the client does not receive the message from the server.
Has anyone got an idea why this isn' working?
Your reading thread is waiting for a newline in the data stream. Just change the server to use:
writer.write("Hello World\r\n");
and you'll get the result you were expecting. Alternatively, you can just close the server socket, and then readLine will return when it reaches the end of the data stream.
You should put the readline in a loop as follows:
public static void main(String[] args) {
final ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(12345);
Thread t = new Thread() {
public void run() {
try {
Socket server = serverSocket.accept();
PrintWriter writer = new PrintWriter(server.getOutputStream(), true);
writer.write("Hello World");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t.start();
Socket client = new Socket("localhost", 12345);
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
// Check this --------------------------------------------------->
String message = null;
while ((message = in.readLine()) != null) {
System.out.println("Received " + message);
break; //This break will exit the loop when the first message is sent by the server
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
You can read this documentation for further explanation: http://download.oracle.com/javase/tutorial/networking/sockets/

Categories

Resources