How to close TCP connection from server in Java - java

Here is use case I need to implement in Java:
Server is listening for push messages from some clients
If client has some data to push into server, it opens TCP connection and sends all messages
When client sends last message (special message saying that this is the last one) server should close connection by starting TCP closing handshake
I have problem with last step because I don't know how to close connection from server site. My current code is bellow. How to initiate connection closing TCP handshake form server site? Thank you for any help.
public class Server{
public static void main(String[] args) throws Exception {
while (true) {
int port = AppConfig.getInstance().getPort();
try (ServerSocket socket = new ServerSocket(port)) {
Socket server = socket.accept();
InetAddress ipAddress = server.getInetAddress();
MessageHandler handler = new MessageHandler(ipAddress);
InputStream in = server.getInputStream();
// reads all bytes from input stream and process them by given handler
processStream(in, handler);
in.close();
server.close();
} catch (Exception e) {
LoggingUtils.logException(e);
}
}
}
private static void processStream(InputStream in, MessageHandler handler) throws Exception {
// implementation is omitted
}
}

You've done it. in.close() closes the input stream, the socket output stream, and the socket.
What you should really close is whatever output stream was attached to the socket, to ensure it gets flushed, and you should probably do that in the processStream() method, with a saver server .close() in a finally block in the calling method.
NB Your socket names are really the wrong way round. It is customary to use ServerSocket serverSocket, and Socket socket = serverSocket.accept().

I may be not totally sure about this one, but I would believe that socket.close() will send all the commands (FIN/FIN-ACK)

Related

Java server socket connection reset

When my SECOND client connect to my server I got this error:
Exception in thread "main" java.net.SocketException: Connection reset
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:200)
at java.base/java.io.DataInputStream.readLine(DataInputStream.java:518)
at Main.main(Main.java:24)
I don't know what am I doing wrong.
FIRST client works normal
My code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class Main {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(50505);;
Socket socket;
while (true) {
socket = serverSocket.accept();
while(socket.isConnected()) {
String v;
DataInputStream in;
InputStream in_sock;
in_sock = socket.getInputStream();
in = new DataInputStream(in_sock);
v = in.readLine();
System.out.println(v);
OutputStream output = socket.getOutputStream();
DataOutputStream out = new DataOutputStream(output);
out.writeChars("123\n");
out.writeChars("123\n");
out.writeChars("123\n");
}
}
}
}
PS: How can I share error on stackoverflow? like code?
So the big issue, like some other people have said, is that your server can only accept one connection because of the lack of multi-threading.
Right now your server waits for a connection to the port specified
socket = serverSocket.accept();
Then while your socket is still connected you read a line from the socket, print it out to System.out, and then write back to the socket all in a loop. Now this comes into issue because next time a client tries to connect to your serverSocket, it can no longer accept connections because your code is stuck in a loop of reading and writing data from one Socket.
The way to fix this is to introduce multithreading in the way that Milen mentioned above.
Your code should look something like this.
public class Main {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(50505);
while (true) {
Socket socket = serverSocket.accept();
SocketHandler h = new SocketHandler(socket);
h.start();
}
}
}
public class SocketHandler extends Thread{
Socket clientSock;
public SocketHandler(Socket sock){
clientSock = sock;
}
public void run(){
while(clientSock.isConnected()) {
String v;
DataInputStream in;
InputStream in_sock;
in_sock = socket.getInputStream();
in = new DataInputStream(in_sock);
v = in.readLine();
System.out.println(v);
OutputStream output = socket.getOutputStream();
DataOutputStream out = new DataOutputStream(output);
out.writeChars("123\n");
out.writeChars("123\n");
out.writeChars("123\n");
}
}
}
Now this code has a loop that accepts connections, and spawns a new thread for every connection!
I would recommend looking at a few things. First, if you check the Java Docs for ServerSocket you will see this constructor
ServerSocket(int port, int backlog)
Creates a server socket and binds it to the specified local port number, with the specified backlog.
The backlog is the number of incoming connections the server socket can hold onto and store in some sort of buffer until they can be accepted. This is useful if a client is connecting when your accepting loop is in the middle of creating the socket handler. I would recommend putting it at the max number of clients you're expecting.
Secondly, look up the Thread class in the Javadocs. To extend Thread successfully you need to overwrite run(). This method is the method that the thread will execute with. To spawn the thread, you call ThreadObject.start(). You can think of start() as just calling run().
From the "Writing the Server Side of a Socket" tutorial from Oracle:
... the server can service them simultaneously through the use of threads—one thread per each client connection.
The basic flow of logic in such a server is this:
while (true) {
accept a connection;
create a thread to deal with the client;
}
The thread reads from and writes to the client connection as necessary.
In that tutorial you'll also find links to a server (KKMultiServer) and thread (KKMultiServerThread) sample implementations.

Java serversocket not detecting lost connection

I have a socket client (on android phone) and server (on PC) both on a wifi network and the server successfully reads data from the client.
However, when I turn off the wifi on the phone the server read just hangs, whereas I was hoping some error would be thrown.
I do have setSoTimeout set on the server, but the read is not timing out.
On the PC netstat still shows an established connection
netstat -na | grep 6668
TCP 192.168.43.202:6668 192.168.43.26:43076 ESTABLISHED
Is there a way to tell if the client host has disappeared, or getting the read to time out?
Here is the server read
if (ss.isConnected()) {
try {
readData();
} catch (java.net.SocketTimeoutException ex) {
logger.warning(ex.toString());
} catch (InterruptedIOException ex) {
logger.warning(ex.toString());
} catch (IOException ex) {
logger.log(Level.WARNING, "Data communication lost will close streams - IOEx - socket status {0}", ss.socketStatus());
closeStreams();
} catch (Exception ex) {
logger.log(Level.WARNING, "Data communication lost will close streams - Ex - socket status {0}", ss.socketStatus());
closeStreams();
}
}
Where readData is,
public void readData() throws IOException {
for (int i = 0; i < data.length; i++) {
data[i] = ss.readDouble();
}
}
ss.readDouble() is,
public double readDouble() throws IOException {
return in.readDouble();
}
And the server connection,
public void connect() throws IOException {
if (serverSocket == null || serverSocket.isClosed()) {
init();
}
logger.log(Level.INFO, "Wait on " + serverSocket.getLocalPort());
server = serverSocket.accept();
serverSocket.close();
logger.log(Level.INFO, "Connected to {0}", server.getRemoteSocketAddress());
out = new DataOutputStream(server.getOutputStream());
in = new DataInputStream(server.getInputStream());
}
Make a timeout, so let's say no data has been sent for 10 minutes, close it in 60 seconds!
Setting a timeout for socket operations
The answer for this question may help you.
This is nature of TCP connection, not java sockets per se. If the remote peer disconects with broken connection, how should your server know that the peer simply has no data to send?
Writting on closed socket will cause exception, read will simply block if client doesnt end tcp connection properly, for the reason above.
If you go through socket API, you will find option to set timeout ( before proceeding with blocking operation).
You could also consider TCP KEEP Alive, which is also exposed by the Socket API.
// Edit: additional information as per the OP comment
When your client connects to server, you create a client socket to communicate with the peer. Your server socket is the one at which you are listening for new client connections. It is the client socket at which you specify keep alive or read timeout because this is the socket from which you read/write.
// your server is actually reference to ClientSocket
server = serverSocket.accept();
// keep alive duh
server.setKeepAlive(true);
serverSocket.close();

Establishing a client server Communication in JAVA?

I want to perform a two way communication between the client and the server and so far i have achieved one way communication.
My code in JAVA looks like,
ServerSide
public class server{
#SuppressWarnings("deprecation")
public static void main(String[] args)
{
try{
ServerSocket s=new ServerSocket(9998);
Socket ss=s.accept();
DataInputStream din=new DataInputStream(ss.getInputStream());
DataInputStream uip=new DataInputStream(System.in);
DataOutputStream dout=new DataOutputStream(ss.getOutputStream());
System.out.println("Enter message to send to client\n");
String stc=uip.readLine();
dout.writeBytes(""+stc);
din.close();
dout.close();
uip.close();
}
catch(Exception e)
{
System.out.println(e);
}`enter code here`
}
}
ClientSide
public class client{
public static void main(String[] args)
{
try{
Socket ss=new Socket("localhost",9998);
DataInputStream din=new DataInputStream(ss.getInputStream());
DataInputStream uip=new DataInputStream(System.in);
DataOutputStream dout=new DataOutputStream(ss.getOutputStream());
String msg=din.readLine();
System.out.println("Received msg is "+msg);
din.close();
dout.close();
uip.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
I tried to get input in the client side and tried to send in the same way to server. but thats not working. Where am i getting wrong? How Should i achieve a two way communication.
In the client side i got input from user and used .writeBytes(value); and performed readLine() in din in the server side as i have done above in one way communication. But that doesn't work. Where am i doing it wrong?
The best approach to create a double communication system is to create two threads one for writing messages and one to receive messages (both on client and server side).
The listening thread receive a message wake itself and do something. If a response is needed it create the response and add it to a queue.
The writing thread periodically check the queue of messages to be sent. If there are it sends them.
This is the best way for bidirectional client server communication.. "dout.shutdownOutput();" code this line after send function in client side.This is the function named as half socket closed it will helps to back and forth communication.

Java Sockets: One Server and Multiple Clients

So I created a basic client-server program in java. It starts out like this:
Client connects to Server
Server asks for Client's name
Client responds with name
Server greets Client
After this, Client speaks and the Server repeats the words back
I got this to work without too much trouble using this tutorial. The problem comes whenever I try to introduce multiple clients. I thought that it would work because I'm using multiple threads, however, the second clients just hangs until the first client quits and then it starts it work (the server does accept input from the second client, but it doesn't respond with anything until the first client quits).
Here is the code I'm using:
import java.net.*;
import java.io.*;
public class Server extends Thread {
private ServerSocket listener;
public Server(int port) throws IOException {
listener = new ServerSocket(port);
}
public void run() {
while(true) {
try {
Socket server = listener.accept();
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("What is your name?");
DataInputStream in = new DataInputStream(server.getInputStream());
String user_name = in.readUTF();
out.writeUTF("Hello "+user_name);
while(true) {
String client_message = in.readUTF();
out.writeUTF(client_message);
}
}
catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int port = 6006;
try {
Thread t = new Server(port);
t.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Can someone explain what I'm doing wrong?
I have looked at the using Runnable instead of Extends Thread, but I ran into even more problems there, so I want to try and work with this first.
Incoming connections are only handled by the line listener.accept();. But after you got a client connected, you're stuck in the while loop. You need to create a new Thread (or Runnable executed on an ExecutorService if you expect high load), and start it, then immediately accept the next connection.
In a nutshell, this is what is going wrong.
You are using exactly ONE thread as the server.
Blocking this thread when you call listener.accept()
This is what you need to do:
Create two classes
1: Server - Similar to what you have now, but instead of doing the actual work of acting as an echo server, it just spawns a new Thread which starts listening on a NEW PORT (which you can select randomly), and sends the client the address for this new port. The client will then get the new port number and would try to connect to the server on the new port.
2: The Echo thread - This starts a new listener on the port passed, and does the job of echoing to whoever is listening.
OR:
You start a UDP server rather than a TCP server, and all this will not matter then, but that is out of the purview of this specific question.

Threading in client-server socket program - proxy sever

I am trying to write a program that acts as a proxy server.
Proxy server basically listens to a given port (7575) and sends the request to the server.
As of now, I did not implement caching the response.
The code looks like
ServerSocket socket = new ServerSocket(7575);
Socket clientSocket = socket.accept();
clientRequestHandler(clientSocket);
I changed the above code as below: //calling the same clientRequestHandler method from inside another method.
Socket clientSocket = socket.accept();
Thread serverThread = new Thread(new ConnectionHandler(client));
serverThread.start();
class ConnectionHandler implements Runnable {
Socket clientSocket = null;
ConnectionHandler(Socket client){
this.clientSocket = client;
}
#Override
public void run () {
try {
PrxyServer.clientRequestHandler(clientSocket);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Using the code, I am able to open a webpage like google. However, if I open another web page even I completely receive the first response, I get connection reset by peer expection.
1. How can I handle this issue
Can I use threading to handle different requests. Can someone give a reference where I look for example code that implements threading.

Categories