Im telneting into a server and it will block the port if I do not disconnect properly. Im already using socket.close(); so I am not sure what I am doing wrong to disconnect completely from the server
//java socket client example
import java.io.*;
import java.net.*;
public class socket_client {
public static void main(String[] args) throws IOException {
Socket s = new Socket();
String host = "1.1.1.1";
PrintWriter s_out = null;
BufferedReader s_in = null;
try {
s.connect(new InetSocketAddress(host, 12656));
System.out.println("Connected");
// writer for socket
s_out = new PrintWriter(s.getOutputStream(), true);
// reader for socket
s_in = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
// Host not found
catch (UnknownHostException e) {
System.err.println("Don't know about host : " + host);
System.exit(1);
}
// Send message to server
String message = "this is the msg";
s_out.println(message);
System.out.println("Message send");
// Get response from server
String response;
while ((response = s_in.readLine()) != null) {
System.out.println(response);
}
// close the socket
s.close();
// close the i/o streams
s_out.close();
s_in.close();
}
}
There is no disconnect sub-protocol in Telnet. All you have to do is close the socket.
I've never seen or heard of a Telnet server 'block a port if I do not disconnect properly'. I have a production Telnet client which does only that, and which has been working correctly for five or six years. And any server at all that doesn't handle unexpected disconnections properly has something very seriously wrong with it.
The problem is elsewhere, possibly in the (unspecified) server itself. To behave as you describe, it would have to completely ignore end of stream conditions, and ignore IOExceptions as well (or else treat them as completely fatal to the entire process). It would also have to be single-threaded. I'm finding it rather difficult to believe in the existence of such a server, or indeed this problem.
NB you only need to close 's_out', the outermost stream/writer you've wrapped around the socket output stream. If you must close the input stream and the socket, do so after closing the output stream/writer.
The socket is blocked since the server side is not handling unexpected socket closing. You have two alternatives - or rather, two steps, if you want to be thorough - to fixing this.
Handle the other end of the connection closing unexpectedly in an
exception handler, and closing the socket when needed.
Having the client send a message to the server when it wants to
close the connection, allowing the server to close the socket, and
then handling that closed socket as a successful operation.
This is an example of server socket code from O'Reilly that gracefully handles unexpected termination:
try {
ServerSocket server = new ServerSocket(5776);
while (true) {
Socket connection = server.accept( );
try {
OutputStreamWriter out
= new OutputStreamWriter(connection.getOutputStream( ));
out.write("You've connected to this server. Bye-bye now.\r\n");
connection.close( );
}
catch (IOException e) {
// This tends to be a transitory error for this one connection;
// e.g. the client broke the connection early. Consequently,
// we don't want to break the loop or print an error message.
// However, you might choose to log this exception in an error log.
}
finally {
// Most servers will want to guarantee that sockets are closed
// when complete.
try {
if (connection != null) connection.close( );
}
catch (IOException e) {}
}
}
catch (IOException e) {
System.err.println(e);
}
Related
Hi and thanks in advance.
I am currently trying to create a client server program where the server responds to the client based on different requests coming in from the client.
Here is what I am trying to do for the first of the requests (the issue is the same for all of the clients different requests to the server, so fixing just this would help me fix all of them):
1) The client connects to the server
2) The client sends logon information to the server
3) The server checks the logon information for validity
4) The server sends a response saying that login was successful.
5) Client receives and displays response.
Here is the Client (the first try block is located in the client frame, the second within an action listener for a button on the client frame):
try
{
mySocket = new Socket("localhost", 2016);
}
catch (UnknownHostException e1)
{
e1.printStackTrace();
}
catch (IOException e1)
{
e1.printStackTrace();
}
try
{
DOS = new DataOutputStream(mySocket.getOutputStream());
DOS.writeUTF(txtName.getText() + " " + txtPassword.getText());
DOS.flush();
DOS.close();
DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());
JOptionPane.showMessageDialog(null, DISLog.readLine());
}
catch(IOException e1)
{
e1.printStackTrace();
}
Server:
System.out.println("Waiting for client....");
ServerSocket myServerSocket = new ServerSocket(2016);
Socket mySocket = myServerSocket.accept();
myClientHandler = new EZFILEHandler(mySocket);
//Log in check
DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());
StringTokenizer ST = new StringTokenizer(DISLog.readLine());
String Name = ST.nextToken();
String Password = ST.nextToken();
//DISLog.close();
boolean Found = myClientHandler.matchUser(Name,Password);
DataOutputStream DOS = new DataOutputStream(mySocket.getOutputStream());
if (Found == true)
{
DOS.writeUTF("You are logged in.");
DOS.flush();
LoggedIn = true;
}
if (Found == false)
{
DOS.writeUTF("You could not log in.");
DOS.flush();
}
Here is the code for the ClientHandler mentioned in the Server code:
public EZFILEHandler(Socket newConnectionToClient)
{
try
{
mySocket = new Socket("localhost", 2016);
}
catch(Exception e)
{
e.printStackTrace();
}
}
Running the above code will give a Socket is closed exception at this line in the client: DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());, so I then tried commenting out the line: DOS.close(); in the client to keep the socket open, but that causes the button which calls the client code to freeze the program and points to this line if I terminate the program: JOptionPane.showMessageDialog(null, DISLog.readLine());.
So my question is this: How do I allow the client and server to respond to each other in different ways without the socket closing or the jswing freezing from not being allowed to finish processing?
Also, how would it be possible for me to allow multiple clients to logon to the server and all their requests still be processed safely?
Thank you.
If you are writing a Swing program, your socket communication should be on its own SwingWorker thread.
Let's ignore that, and pretend it is just debugging code, not intended to stay.
DISLog.readLine() will read until it reaches the newline character, or the end of the input stream. The server is executing (say) the following:
DOS.writeUTF("You are logged in.");
DOS.flush();
No newline there. And flush() does not close the stream; it simply ensures all the characters are sent, not left in the buffer to be combine with the next set of characters to send.
Catch-22? Yup! The client is waiting for \n, and the server is waiting for more commands from the client.
Change the client to use readUTF().
Update Looks like you need to change the server to use readUTF() as well. The server is probably not getting past the new StringTokenizer(DISLog.readLine()) call unless the client closes the socket.
I already read some threads here on stackoverflow, also some tutorials, but I don't find a solution to my problem.
I have Java client which connects to a server, then sends exactly one line to the server, and I get 2 or 3 lines as a response.
Here is my code:
public static void main(String[] args) {
String message;
String response;
try {
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
Socket clientSocket = new Socket(hostname, port);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
message = inFromUser.readLine();
outToServer.writeBytes(message + '\n');
// here my program "freezes"
while ((response = inFromServer.readLine()) != null) {
System.out.println("response: " + response);
}
clientSocket.close();
} catch (UnknownHostException e) {
System.out.println("Unknown Host");
} catch (IOException e) {
System.out.println("IO Exception");
}
}
My problem is, I can read every line of the response, but my program won't exit. The line clientSocket.close(); gets never called. What am I doing wrong?
Presumably your server isn't closing the connection - therefore the underlying stream for the reader isn't closed... at any point the server could send more information. readLine() only returns null when the stream has been closed, i.e. there will definitely not be any more data.
Now we don't know anything about the protocol here, but if the expected behaviour is that the client won't send any more information, and the server will close the connection, then the bug is in the server. If the protocol states that the server will keep the connection open, then the bug is in your client code and you need to work out how to detect the end of data (or send some sort of ack that will cause the server to close the connection, or whatever).
I am writing Socket program , Here Client Sends a String through Stream , Server Process it and writes back to Client. My problem is, after Server process the String , it Writes back to Stream but in client It can't able to read the Stream its showing exception as Exception in while: java.net.SocketException: socket closed Here is my code,
Client ,
public void run() {
while (true) {
try {
// Open your connection to a server, at port 1231
s1 = new Socket("localhost", 1231);
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream(s1out);
InputStream in=s1.getInputStream();
DataInputStream dis=new DataInputStream(in);
String s = br.readLine();
dos.writeUTF(s);
dos.flush();
dos.close();
System.out.println(dis.readUTF());//it is the String from Server after processing
dis.close();
} catch (IOException ex) {
// Logger.getLogger(SimpleClient.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Exception in while: " + ex);
}
}
In Server
public void run()
{
while(true){
try {
System.out.println("Waiting for connect to client");
s1=serverSocket.accept();
s1In = s1.getInputStream();
dis = new DataInputStream(s1In);
out=s1.getOutputStream();
dos=new DataOutputStream(out);
String clientData=dis.readUTF();
//processing task String
dos.writeUTF("Bus Registered Successfully");
dos.flush();
}
}
Here I am not able to read Bus Registered Successfully at client side . How to Solve this.?
Well there are many things not right in your program. But first let me answer your question ... you are closing the socket just after writing the stream ... so server throws exception, just remove dos.close(); just after the dos.flush();. It will run fine.
Now back to the programming practices ...
1) Server should accept the connection in a while(true) loop and then make a new thread. So following statement should not be the part of run method.
System.out.println("Waiting for connect to client");
s1=serverSocket.accept();
s1In = s1.getInputStream();
dis = new DataInputStream(s1In);
out=s1.getOutputStream();
dos=new DataOutputStream(out);
2) There is no need of run method in client. Because Every new client will be a new program that has its own variables and socket.
A quick look shows me that the reason the socket is closed is because you used dos.close().
Closing a DataInputStream (or PrintStream, or any similiar stream) will close the underlying socket.
Just take out dos.close().
You can also move the dos.close() to the very end of the try block. As a general rule, don't close anything related to the socket until you're done with the socket.
Client:
Open socket:
Socket socket = new Socket(host,port);
Write data:
socket.getOutputStream().write("str");
socket.getOutputStream().flush();
Read data:
response = socket.getInputStream().read();
Close connection and socket:
socket.shutdownInput();
socket.shutdownOutput();
socket.close();
Server:
Socket clientSocket = serverSocket.accept();
message = clientSocket.getInputStream().read();
clientSocket.getOutputStream().write("str2");
clientSocket.isConnected() returned true, and the server does not see that the client is disconnected. How to detect that the client is disconnected?
I'm try use this:
try {
while (true) {
message = clientSocket.getInputStream().read();
clientSocket.getOutputStream().write("str2");
}
} catch (IOException e) {
clientSocket.close();
}
But it doesn't work.
A common approach is that the client sends a "QUIT" message to the server. The server will then close it's socket.
The other approach is to do I/O on the server socket and catch the exceptions that you'll get when the client is gone.
The latter approach has a couple of drawbacks:
It will take some time for the server to give up trying to reach the client (that can take 2 minutes)
The error message might not always be the same. Usually, you'll just get a SocketException with the error message from your OS.
I have a Java TCP server which, when a client connects to it, outputs a message to the client every 30 seconds. It is a strict requirement that the client does not send any messages to the server, and that the server does not send any data other than the 30-second interval messages to the client.
When I disconnect the client, the server will not realise this until the next time it tries to write to the client. So it can take up to 30 seconds for the server to recognise the disconnect.
What I want to do is check for the disconnect every few seconds without having to wait, but I am not sure how to do this given that a) the server does not receive from the client and b) the server cannot send any other data. Would anyone please be able to shed some light on this? Thanks.
Even though your server doesn't "receive" from the client, a non-blocking read on the client socket will tell you that either there's nothing to be read (as you expect), or that the client has disconnected.
If you're using NIO you can simply use a non-blocking Selector loop (with non-blocking sockets) and only write on your 30 second marks. If a SelectionKey is readable and the read on the SocketChannel returns -1 you know the client has disconnected.
EDIT: Another approach with blocking is simply to select with a 30 second timeout. Any client disconnects will cause the select to return and you'll know which ones those are via the read set. The additional thing you'd need to do there is track how long you were blocked in the select to figure out when to do your writes on the 30 second mark (Setting the timeout for the next select to the delta).
Big Edit: After talking to Myn below, offering complete example:
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
// Set a 1 second timeout on the socket
clientSocket.setSoTimeout(1000);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
long myNextOutputTime = System.currentTimeMillis() + 30000;
String inputLine = null;
boolean connected = true;
while (connected)
{
try {
inputLine = in.readLine();
if (inputLine == null)
{
System.out.println("Client Disconnected!");
connected = false;
}
}
catch(java.net.SocketTimeoutException e)
{
System.out.println("Timed out trying to read from socket");
}
if (connected && (System.currentTimeMillis() - myNextOutputTime > 0))
{
out.println("My Message to the client");
myNextOutputTime += 30000;
}
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
Worth noting here is that the PrintWriter really moves you far away from the actual socket, and you're not going to catch the socket disconnect on the write (It will never throw an exception, you have to manually check it with checkError()) You could change to using a BufferedWriter instead (requires using flush() to push the output) and handling it like the BufferedReader to catch a disco on the write.
If you are managing multiple clients then I guess you would be using Non-Blocking sockets (If not then consider using Non-Blocking). You can use Selector to monitor all the connected sockets to check if they are readable or writeable or there is some Error on that socket. When some client disconnects, your Selector will mark that socket and will return.
For more help google "Socket Select function"