My client/server application currently keeps opening and closing new connections every time it wants to send/receive data. I'm trying to change it so it will have one persistent connection.
The problem I'm having is the socket's DataInputStream on the server keeps throwing EOFException's when I just want it to block until it receives the next batch of data.
I thought about just simply writing the server like this...
while socket is open {
while at socket's DataInputStream's EOF {
wait a second
}
//If we're here, then we have some data
do stuff
}
... but this is extremely ugly and not the proper way to block until some data is received.
Is there a cleaner way to tell the socket to block until there's some data to read? I've tried read() and readFully(), but neither work.
If you are getting EOFException, it means the connection is gone. You cannot wait on a connection that's closed. Keep working on your client code so that it doesn't close the connection. On the server side, any of the read methods will block until data is available without further effort from you.
Related
I'm writing a simple Java server that accepts multiple client socket connections. I'm using a separate thread to handle each client/socket. Considering I have set up the networking including the BufferedReader, InputStreamReader, and FileWriter etc. for this client/socket.
My code is :
//run method of my Runnable everytime a new client connects
public void run(){
String message = null;
while((message = bufferedReader.readLine())!=null){
System.out.println(message+"/n");
//do some other things like writing this message
//to another client or saving it in a file, etc
}
}
Does this keep the client socket open? or does the socket eventually makes the thread goes dead when it's done reading from the stream
Will it keep waiting for more/new messages/data from the client socket even after it's done reading for the first time?
Once the server accept client request, the server is capable of exchanging messages with the client endlessly until the socket is closed with its streams.
To allow continuity in communication, you have to read from the stream inside a while loop and only exit when the client sends a termination request. So in your case the client socket is open until you read, once you exit from the loop your connection will be terminated.
Where did you create the bufferedReader ?
The thread will end when the readLine call returns null. That happens when the reader reaches the "end of stream". If the BufferedReader is wrapping an input stream associated with a socket, then "end of stream" will be triggered by the socket connection closing; e.g. because the remote client / server closed it.
There is no code shown here to close the BufferedReader. It will be closed if either something else calls close on it, or if the BufferedReader object becomes unreachable. In the latter case, the reader and the underlying socket stream and socket will eventually be closed when the GC finalizes the objects.
My question is does this keep the client socket open? Or does the socket and eventually the thread goes dead when it's done reading from the stream, or will it keep waiting for more/new messages/data from the client socket even after it's done reading for the first time?
It depends. See above.
The point is that the code as written reads until there is no more to read. Not until "it is done". Or to put it another way "it is done" ... if and only if the other end tells it so, by closing the stream.
In java client socket programming, I am trying to get exception in the case where user writes data on socket when internet connection is not available.Most of the time I get IoException while writing in this situation but sometime I dont get any exception in this case.
Can anyone tell me where that data goes when any Exception does not arise.
It goes into the socket send buffer in the kernel. In general you won't get an exception on the first write after an outage, because of this buffer. You'll get it on a subsequent write, when the kernel has had time to time out trying to send the data in the buffer.
I am in the process of developing a game and I have a question.
I have a client where a user can log in to the game or disconnect using a unique account stored on a database.
How do I properly close a server on log out and re open on log in? Or should I never close the socket? The same question goes for DataInputStream and DataOutputStream.
I keep getting connection reset client sided, so I don't know what the best way to handle logging in/logging out within the same client runtime.
Thanks. :)
Just close the socket. That will terminate the corresponding thread at the server. One login should equal one socket.
You should do that by closing the outermost stream or Writer wrapped around the socket output stream. That flushes it and closes the other streams and the socket. Closing the input stream and the socket before this is incorrect, and doing so afterwards is redundant, but if you must do it it must be done after, not before, otherwise again you miss a flush.
I am running 2 threads in my applciation. One to check for incoming packets and one to process and send packets. They both do it on the SAME STREAM.
Example for 1:
while (connection open) {
in.readObject() instanceof ...
}
Example for 2:
while (connection open) {
processPacket(in)
}
I'm pretty sure EOFException is when the threads try and use the stream at the same time. It's not a constant EOF but only like every 1 second I get an EOF the rest works fine. So that's why I suspect that they overlap and try to use the stream at the same time.
If that is the problem, anyone know how do I synchronize them to do it after another while still keeping the current update speed and using two threads?
I need two threads because the check for incoming waits in a line until a packet gets recived and I need the server to constantly send process and check for packets.
How do I fix the EOFException?
If your getting an EOFException, it typically means the other side hung up. You usually get these on the read side.
Here's a similar SO question
Edit 1: The question is really why is the socket closed. It can be for any number of reasons, a programmable timer on the server side checking for no data within X minutes, a firewall closing the connection, a network interruption, etc..
Both threads shouldn't be reading the same Stream.
You should read the objects and put them in a ConcurrentLinkedQueue, then from the second thread you can check the queue for objects ready to process.
EOFException is 'normal'. It happens on one thread too. Your architecture of reading in two threads simultaneously cannot possibly work, but it isn't the cause of this problem. The cause is that the peer closed the connection. This is going to happen. Unless your application protocol contains message counts or a close notify or some other means of predicting EOS, it is going to get EOFExceptions, or readLine() returning null, or read() returning -1, depending which read methods you are calling.
In some circumstances I wish to send an error message from a server to client using non-blocking I/O (SocketChannel.write(ByteBuffer)) and then disconnect the client. Assuming I write the full contents of the message and then immediately disconnect I presume the client may not receive this message as I'm guessing that the OS hasn't actually sent the data at this point.
Is this correct, and if so is there a recommended approach to dealing with this situation?
I was thinking of using a timer whereby if I wish to disconnect a client I send a message and then close their connection after 1-2 seconds.
SocketChannel.write will in non-blocking mode return the number of bytes which could immediately be sent to the network without blocking. Your question makes me think that you expect the write method to consume the entire buffer and try asynchronously to send additional data to the network, but that is not how it's working.
If you really need to make sure that the error message is sent to the client before disconnecting the socket, I would simply enable blocking before calling the write method. Using non-blocking mode, you would have to call write in a loop, counting the number of bytes being sent by each invocation and exit the loop when you've succeeded to pass the entire message to the socket (bad solution, I know, unnecessary code, busy wait and so on).
you may be better off launching a thread and synchronously write data to the channel. the async api is more geared toward "one thread dispatching multiple channels" and not really intended for fire and forget communications.
The close() method of sockets makes sure, everything sent using write before is actually sent before the socket is really closed. However this assumes that your write() was able to copy all data to the tcp stacks output window, which will not always work. For solutions to this see the other answers.