I found the same problem in this post, but i think it wasn't solved.
i'm going to be brief, this is my code:
try {
Socket pacConx = new Socket(ip, Integer.parseInt(port));
DataInputStream dataIn = new DataInputStream(pacConx.getInputStream());
DataOutputStream dataOut = new DataOutputStream(pacConx.getOutputStream());
while(){...}
} catch (IOException e) {
logger.fatal("error", e);
}finally{
if (dataIn != null) {
dataIn.close();
}
if (dataOut != null) {
dataOut.close();
}
if (pacConx != null) {
pacConx.close();
}
}
First, i connect to the server using the code above, and it succeed.
But, when i try to REconnect to the same server and port after a while, i cannot reconnect.
Apparently the first socket is still "alive" in the serverSide.
is the a solution to my peoblem ?
Is there a way that i can close the other "alive" socket ?
Try
...
dataOut.flush();
dataOut.close();
...
Paste error message or/and full stack trace.
You need to initiate an orderly disconnect. After calling flush on the streams, and before calling close on the socket, add this:
pacConx.shutdownInput();
pacConx.shutdownOutput();
That tells the remote end you're finished and allows it to dismantle the port without waiting to make sure there isn't data still in transit.
For about 2-4 minutes after you close the socket it will hang in "CLOSE_WAIT" state on the server. This is a normal part of the TCP/IP protocol to handle delayed packets still wandering around in the network.
This should be handled by your server code. Is it unbinding its listen socket while handling a request and trying to re-establish it after the close? If so, it should either leave the listen up during processing or re-establish it with a SO_REUSEADDR option.
Related
I am making an HTTP server as a project for a class that I am attenting ,for a week now I have stuck trying to find a solution .I have a DataInputStream and I need to wait for the client to send me the http request,there can pass hours before that happens since the connection remains open.This is my code
DataInputStream dis=new DataInputStream(socket.getInputStream());
DataOutputStream dos =new DataOutputStream(socket.getOutputStream());
while(!socket.isClosed()){
try{
/**wait until there are new data in to the stream,if the connection is no more alive then close it*/
while(dis.available()==0){
if(alive==false){
socket.close();
break;
}
}
/*at this point the stream has new data ,or the alive attribute has been set to false */
if(!socket.isClosed()){
/*parse the request text */
Request request=new Request(dis,this);
/*generate a response based on the request*/
Response response=new Response(request,this);
/*send the response back to the client*/
response.send(dos);
/*log the details of the communication*/
Logger.log(toString(request,response,socket));
/*if the request is bad formatted or it has its Connection header set to close , close the connection after sending the response*/
if(request.isBadRequest() || !"keep-alive".equalsIgnoreCase(request.getHeader("Connection"))){
close();
}
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
on the while(dis.available()==0) part I am waiting for the stream to have some data,but the problem is that if I have many connections my server starts to get very much cpu time slowing my computer down since it just hangs doing the loop again and again not giving the chance to the cpu to do good scheduling.If the dis.available() was a blocking command then everything would had been perfect.Any workaround?
InputStreams already block in the read methods while no data is available.
You don't need a single one of these available() calls or loops around them.
You should also note that Socket.isClosed() only returns true if you have closed the socket. It doesn't tell whether the peer has closed the connection.
I am writing an app for android 4.2, currently debugged on a Samsung s2+.
The app establishes a connection to a server using a Socket, and the server is using a ServerSocket and the establish()-method to get its socket. So far so good. Since I have to make all the networking in android in a new thread, I created a new class extending Thread which communicates with an underlying Activity (for user input) using a BlockingQueue. The threads run method:
public void run() {
Socket s = null;
try {
s = new Socket(info.getIp(), 1337);
} catch (IOException e) {
e.printStackTrace();
}
String code = null;
try {
code = queue.take();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Log.e("DONE", code);
PrintWriter out = null;
try {
out = new PrintWriter(s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
out.write(code);
out.flush();
}
The connection is up and running, and the logged message "DONE"+code is logged. However, nothing is received on the server side until I force close the app. Is an android thread not able to flush data?
EDIT: If close the socket immediately after writing to it, the text arrives without having to force close the app. Why can't I read the text in the server if the socket is still alive?
try add a newline to the string you sent to server , something like :
out.write(code+"\n");
out.flush();
and as EJP said above put the out.write inside the try / catch
A socket connection only provides the ability to send and receive bytes. As soon as the client sends a byte, the server will receive it. Also, as soon as a client is disconnected, the server will know about it - this is about the extend of what you get from sockets.
The concept of a message does not exist at this level. A message is instead defined by whatever lies above the socket, so most protocols use one or more of three different ways to chunk streams of bytes into "messages"
a special byte or sequence of bytes indicates the end of the message (a new line for example, which seems to have been your case :)
each message starts with x bytes which provide the length of the message (so a simple "05aaaaa02bb" stream of bytes might mean that 2 messages were send - "aaaaa" and "bb"
the entire socket connection lasts for a single message (end of message comes when the connection is closed). This is how HTTP 1.0 works for example.
I want to listen to incoming packets on port 19132 and print them out as they come, but so far my code doesn't exactly print anything at all. There is a server forwarding the packets through port 19132 to my computer, and the port is open and enabled, but still nothing is printed.
public static void listenToPort(){
try{
ServerSocket serverSocket = new ServerSocket(19132);
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
try{
System.out.println(in.readLine());
}
catch(IOException e){
System.out.println("Connection to server lost!");
System.exit(1);
break;
}
}
}
catch(IOException e){
System.out.println(e.getMessage());
}
}
On the server side there is info being sent, but the client program (this script) doesn't receive anything, what's the problem?
You are reading lines, not 'packets'. If the data being sent to this port doesn't contain newlines, readLine() will block forever, or until the peer closes the connection.
On the other hand when it does read something, or EOS, your code will spin forever printing null, because you aren't checking for readLine() returning null, at which point you must close the socket and exit the loop.
Not to mention, it might be entirely possible that the System.exit doesn't give enough time for the console to flush it's output (i'm not 100% sure if System.exit will or won't cause a flush in System.out and System.err).
Why don't you attach a debugger to your server process and see if it's even getting past the in.readLine()? As one of the other posters mentioned, if you're not sending a newline character, in.readLine() would block until you do.
Secondly, you shouldn't really use System.exit. It's bad form in most cases and leads to people wondering why the hell an app would just randomly quit. If you want to exit an app, you should allow the code to return back to the main() method, and from there you can do a System.exit if necessary.
Basically I want to create a rock solid server.
while (keepRunning.get()) {
try {
Socket clientSocket = serverSocket.accept();
... spawn a new thread to handle the client ...
} catch (IOException e) {
e.printStackTrace();
// NOW WHAT?
}
}
In the IOException block, what to do? Is the Server socket at fault so it need to be recreated? For example wait a few seconds and then
serverSocket = ServerSocketFactory.getDefault().createServerSocket(MY_PORT);
However if the server socket is still OK, then it is a pity to close it and kill all previously accepted connections that are still communicating.
EDIT: After some answers, here my attempt to deal with the IOException. Would the implementation be guaranteeing keeping the server up and only re-create server socket when only necessary?
while (keepRunning.get()) {
try {
Socket clientSocket = serverSocket.accept();
... spawn a new thread to handle the client ...
bindExceptionCounter = 0;
} catch (IOException e) {
e.printStackTrace();
recreateServerSocket();
}
}
private void recreateServerSocket() {
while (keepRunning) {
try {
logger.info("Try to re-create Server Socket");
ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(RateTableServer.RATE_EVENT_SERVER_PORT);
// No exception thrown, then use the new socket.
serverSocket = socket;
break;
} catch (BindException e) {
logger.info("BindException indicates that the server socket is still good.", e);
bindExceptionCounter++;
if (bindExceptionCounter < 5) {
break;
}
} catch (IOException e) {
logger.warn("Problem to re-create Server Socket", e);
e.printStackTrace();
try {
Thread.sleep(30000);
} catch (InterruptedException ie) {
logger.warn(ie);
}
}
}
}
If in doubt, you could try re-creating the server socket, using the same port. If the socket has been closed, then the creation will succeed and you can continue processing new connections. The old connections are gone, but that's outside of your control since the socket was closed. If the socket was not closed, then creating a new instance will fail since the port is still in use, which you can just ignore - i.e. don't replace the current server socket reference.
In general, clients should also assume that connections will be broken and that reconnection is necessary. In other words, it's not just the server that has to be robust - clients should also anticipate connection errors and reconnect.
You can get an IOException on an accept() if the server socket is closed (by you) or you run out of resources, e.g. file handles. Either way, there is not much you can do about it. If the serverSocket is closed (you can test for this) you probably had a good reason to do this. If you run out of resources, you will either have to increase your resource limit, which requires a restart of your application, or you have a resource leak.
Make sure you differentiate between different IOExceptions you might receive. Is it an exception on creating a connection? Is it an exception once a connection has already been established?
The only code you gave is for accept()ing. Generally speaking, an IOException usually means an error on any layer on the physical network.
Probably the best fallback behavior you can implement is to wait for a certain time quantum, and then try to reconnect. Assume you most possibly will not be able to reconnect, since you have lost network connection for more than a temporary period. Make sure you handle this gracefully. As #mdma mentioned, this must be supported by your clients as well.
However if the server socket is still
OK, then it is a pity to close it and
kill all previously accepted
connections that are still
communicating.
Please note that closing the server socket will NOT close previously accepted connections. As soon as a connection has been accepted it lives a separate, joyful life at a different port.
I'm accepting a connection from a client and then passing that connected socket off to another object, however, that socket needs to be non-blocking. I'm trying to use getChannel().configureBlocking(false) but that does not seem to be working. It needs to be non-blocking because this the method below is called every 100ms. Is there some other way that I should be making this non-blocking? Thanks for any help!
public void checkForClients() {
DataOutputStream out;
DataInputStream in;
Socket connection;
InetAddress tempIP;
String IP;
try {
connection = serverSocket.accept();
connection.getChannel().configureBlocking(false);
System.err.println("after connection made");
in = new DataInputStream(connection.getInputStream());
out = new DataOutputStream(connection.getOutputStream());
tempIP = connection.getInetAddress();
IP = tempIP.toString();
System.err.println("after ip string");
// create a new user ex nihilo
connectedUsers.add(new ConnectedUser(IP, null, connection, in, out));
System.err.println("after add user");
} catch (SocketTimeoutException e) {
System.err.println("accept timeout - continuing execution");
} catch (IOException e) {
System.err.println("socket accept failed");
}
}
Two things:
Why aren't you using a ServerSocket if you're listening for connections?
If you want to accept multiple clients you want to use a loop.
The basic structure of a multi-client server is:
while (true) {
// accept connections
// spawn thread to deal with that connection
}
If the issue is blocking on the accept() call, well that's what accept() does: it blocks waiting for a connection. If that's an issue I suggest you have a separate thread to accept connections.
See Writing the Server Side of a Socket.
I would expect your code to block on the accept call, never getting to the configureBlocking call.
I typically spin off a separate thread for each socket connection, and let it block until a connection is actually made/accepted This allows the main thread to continue unblocked while it is waiting for client connections.
If you're looking for non-blocking sokets, my suggestion is to use Selectors and ServerSocketChannels with the NIO package.
http://java.sun.com/j2se/1.4.2/docs/guide/nio/
If the typical blocking socket doesn't give you the availability you need (a connection every 100ms does seem tight). You should look at a non-blocking socket. Here is a tutorial. You can also look at Apache MINA to make this easier.
One approach is to use an I/O loop (event loop) in a single threaded environment. Take a look at Deft web server for inspiration. (Especially the start() method in IOLoop)