I have to implement a Server which should accept more connections. Without any deeper thoughts i decided to use the new JAVA NIO.2 classes.
My current approach is:
final Semaphore wait = new Semaphore(1);
while(true){
wait.acquire();
this.asyncSocket.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
#Override
public void completed(AsynchronousSocketChannel result, Void attachment) {
wait.release();
asyncSocket.accept(null, this);
...
}
...
}
}
if i don't add the semaphore, i get an AcceptPendingException. It works, however, i don't know if thats the proper way to implement a server which can handle more open sockets.
Another Approach was:
final Semaphore wait = new Semaphore(1);
while(true){
wait.acquire();
final Future<AsynchronousSocketChannel> futureChannel = this.asyncSocket.accept();
this.exec.execute(new Runnable() {
#Override
public void run() {
try (final AsynchronousSocketChannel clientChannel = futureChannel.get()) {
wait.release();
try (ObjectInputStream ois = new ObjectInputStream(Channels.newInputStream(clientChannel))) {
final Command cmd = (Command) ois.readObject();
cmd.execute(util, clientChannel, null, logger).run();
}
} catch (IOException | InterruptedException | ClassNotFoundException | ExecutionException e) {
e.printStackTrace();
}
}
});
Why i'm unhappy with both solutions?
Unfortunately, in both implementations, the server leaves a lot of open sockets in state TIME_WAIT, although i'm closing the it on the server as well on the client side..
So actually i've 2 questions:
Whats a proper way to use AsynchronousServerSocketChannel to implement a Server wich accepts more connections.
How to get rid of the open sockets in state TIME_WAIT
EDIT:
private <T extends Serializable> T sendCommand(final Command<T> command) throws ExecutionException, InterruptedException, IOException, ClassNotFoundException {
T result = null;
try (final AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(channelGroup)) {
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
channel.connect(this.mwInfo.getNextMiddleware()).get();
final OutputStream os = Channels.newOutputStream(channel);
final InputStream is = Channels.newInputStream(channel);
try (final ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(command);
oos.flush();
try (final ObjectInputStream ois = new ObjectInputStream(is)) {
result = (T) ois.readObject();
}
}
}
return result;
}
Thanks in advance!
I can only answer the second question (no knowledge of Java socket specifics). To get rid of those sockets you must implement 'graceful shutdown' protocol on socket. That is, one socket does shutdown on send, another one does shutdown on send upon seing that, than sockets to shutdown on recv. This will ensure no sockets will stay in TIME_WAIT state.
The other option would be to fiddle with SO_LINGER option of the socket, but this is ill-advised.
I also notice, that people seems to just use SO_REUSEADDR as a universal solution. You can't bind to a port? Specify SO_REUSEADDR and all your problems will go away... and this is wrong! If SO_REUSEADDR is universal solution, why is it not ON by default? Because it is dangerous. When you specify SO_REUSEADDR, you create another socket on the same port and now you can start seeing messages from the previous connection! This is not very likely to happen, of course. But it can happen! Imagine what kind of bug would it be to troubleshoot!
Related
First question here on StackOverflow, so please excuse me if I ask this incorrectly.
Basically, I'm writing a Multicast Client that indefinitely listens to a multicast address until the user types "quit" into the console. I've found that setting SO_TIMEOUT for the MulticastSocket, checking if "quit" has been typed, and then returning to the receive method call doesn't really work since a packet could be sent right after the timeout and the check of the console blocks. So I believe the best option is to simply have 2 threads going where one listens on the socket and blocks until it receives something, and the other thread listens to the console until told to quit. The only issue I have is that I'm unsure of how to go about having the console listening thread tell the socket thread to close the socket and terminate. System.end() would work but I fear that I'd leave a socket open, etc.
TLDR; Is there a way for the main method of a class to start a thread, and then respond a specific way once that thread ends? I need to listen to the console on one thread and a MulticastSocket on another, or just in the main of the client class.
Thanks everyone.
I would call Socket.close() to close the socket. This will produce an IOException in that thread. so before doing this I would set a flag like closed = true; and have the other thread check this before printing the error i.e. don't print an IOException if you have been closed. Something like this.
public class SocketListener implements Runnable, Closeable {
final MulticastSocket socket;
final Consumer<DatagramPacket> packetConsumer;
volatile boolean closed;
public SocketListener(MulticastSocket socket, Consumer<DatagramPacket> packetConsumer) {
this.socket = socket;
this.packetConsumer = packetConsumer;
}
#Override
public void run() {
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
try {
while(!closed) {
socket.receive(packet);
packetConsumer.accept(packet);
}
} catch (IOException e) {
if (!closed)
e.printStackTrace();
}
}
#Override
public void close() throws IOException {
closed = true;
socket.close();
}
}
for example, in your main thread you can do
MulticastSocket socket = ...
Consumer<DatagramPacket> packetConsumer = ...
try (SocketListener listener = new SocketListener(socket, packetConsumer)) {
boolean finished = false;
do {
// read from the console
if (some condition)
finished = true;
} while(!finished);
} // calls close() for you.
I wrote a client which basically just open a socket and send content over the connection. ( the content follows the Http protocol)
The problem I'm facing regards to the question - how and when should i close the connection.
The issue is that the connection sometime closes too early ("FIN" is sent to the server before the server answered).
in this case the server's answer is lost.
I tried to use Thread.sleep before closing the connection but nothing seems to affect the time between the content is sent and the "FIN" message is sent. (viewed in Wireshark)
The answer sometimes arrive and sometimes not ( race condition).
How can i delay the "FIN" message so i won't miss the server's response?
i added the relevant class. The relevant function is sendContentOverSocket
public class SocketClient {
private String hostName;
private int portNumber;
private Socket ConnectionSocket;
public void init(String hostName, int portNumber){
this.hostName = hostName;
this.portNumber = portNumber;
this.ConnectionSocket=createSocketConnection();
}
private Socket createSocketConnection() {
Socket socket = null;
try {
socket = new Socket(this.hostName, this.portNumber);
return socket;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
public void sendContentOverSocket(String content) {
try {
PrintWriter out = new PrintWriter(
ConnectionSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(
ConnectionSocket.getInputStream()));
out.print(content);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.close();
in.close();
ConnectionSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP works with a concept called a half close.
When you close the socket that is an indication that you are not going to send anymore.
In your explanation I see "FIN is sent to the server before the server answered", if you are the client, that would mean that you have performed a close on the socket.
If you expect a result from a server within a certain time frame you need some kind of timing mechanism, possibly making use of select in combination with a timeout.
If the server closes his end of the connection, you detect this by receiving bytes in receive. Usually this means that you have to close the socket too.
So in conclusion there is 3 reasons for you to close the socket :
the server closes his end of the socket basically saying i am not going to send anymore
you have waited for a while and you are tired of waiting and decide to close the socket yourself.
any other error conditions but usually they all appear like receiving 0 bytes or a negative number.
You should close the connection after you've read the response, of course. Difficult to see the mystery here. No sleeps. If you don't read the response (a) you can't know whether the request succeeded or failed, and (b) the server is liable into encounter an exception as well.
Your code is poor quality. All those methods should propagate exceptions instead of catching them internally and returning null.
In case of Java 7, since all three classes, i.e. Socket, PrintWriter, BufferedReader, implement AutoCloseable and based on the fact, that you want to close socket right after you invoke sendContentOverSocket(String content) try to use the following code:
public class SocketClient {
private String hostName;
private int portNumber;
public void init(String hostName, int portNumber) {
this.hostName = hostName;
this.portNumber = portNumber;
}
public void sendContentOverSocket(String content) {
try (Socket socket = new Socket(this.hostName, this.portNumber);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
out.print(content);
} catch(IOException e) {
//Appropriate exception handler
}
}
}
In this case Java will close all resources properly by itself.
If you use Java 6 or earlier try to use try-finally block instead:
solved.
i now understand how it works.
what i was missing in the client is the attempt to read from the input Stream.
When you try to read
while ((inputFromServer = in.readLine()) != null)
the client waits for input. The only thing that will break this loop is the server closing the connection.
after that happens you can safely close the connection on the client side. No need to delay the FIN and such...
I'm facing this issue working with a ServerSocket inside one of my bundles, let's just call it: FooBundle.
This FooBundle has, among others, a SocketListener.java class. This class is a Thread and to make a little overview of it, I'll paste some pseudocode:
public class SocketListener implements Runnable{
ServerSocket providerSocket;
Socket connection = null;
private boolean closeIt = false;
public void run() {
try {
//Create the server socket
providerSocket = new ServerSocket(41000, 10);
} catch (IOException e1) {
//catching the exception....
}
while(!closeIt){
try{
connection = providerSocket.accept();
in = new Scanner(new InputStreamReader(onnection.getInputStream()));
while(in.hasNext() !=false)
message = message + " "+in.next();
// bla bla bla...
} catch (IOException e) {
//bla bla...
}
finally{
try{
if (message.equalsIgnoreCase("bye"))
providerSocket.close();
closeIt = true;
}
catch(IOException ioException){
//........
}
}
As you can see, it's a simple thread that waits for a connection until the message it receives from one of the SocketClients is "bye".
This is the problem I'm facing right now: When the Bundle is stopped, I do need to restart the entire OSGi framework : If I try to restart the bundle, a java.net.BindException message is thrown: "Address already in use". So, I stopped the bundle but the socket hasn't been closed.
In OSGi, you need to take care of what the stop() method inside the Activator must include, but I just can't pass any reference of an anonymous thread to the Activator.
Imagine that this is my class diagram inside the bundle:
**FooBundle**
|__FooBundleActivator
|__FooImpl
|__SocketListener (thread)
The SocketListener thread is called from the FooImpl class as an anonymous thread.
My question is: Is there any appropiate method to have such control of anonymous threads and specifically in my case, of non-closing socket ports, inside the OSGi paradigm?
Thanks in advance.
If your bundle is told to stop then assume the guy doing the stopping knows what he is doing. Yes, your protocol expects the 'bye' but shit happens, any protocol that has problems with these things is too fragile for the real world. In general, all your tasks in OSGi should have a life cycle. So this would be my code (using DS instead of activators).
#Component
public class ProtocolServer extends Thread {
volatile ServerSocket server;
volatile Socket connection;
public ProtocolServer() {
super("Protocol Server on 4100"); // to identify the thread
}
#Activate void activate() {
setDaemon(true);
start();
}
#Deactivate void deactivate() {
interrupt();
// best effort close (even if null)
try { server.close(); } catch(Exception e) {}
try { connection.close(); } catch(Exception e) {}
join(10000); // waits 10 secs until thread exits
}
public void run() {
// loop for active component
while( !isInterrupted() )
try {
doServer();
} catch( Exception e) {
log(e);
// bad error, accept failed or bind failed
// or server socket was closed. If we should remain
// active, sleep to prevent overloading the
// system by trying too often, so sleep
if ( !isInterrupted() )
try { Thread.sleep(5000); } catch(Exception e) {}
}
}
private void doServer() throws Exception {
server = new ServerSocket(4100)
try {
while( !isInterrupted() )
doConnection(server);
} finally {
server.close();
}
}
private void doConnection(ServerSocket server) throws Exception {
connection = server.accept();
try {
doMessages(connection);
// the pseudo code exits here, but that seems
// kind of weird? If desired, interrupt
// this object, this will exit the thread
} catch( Exception e) {
log(e); // the connection failed, is not uncommon
} finally {
connection.close();
connection = null;
}
}
private void doMessages(Socket connection) {
MyScanner s = new MyScanner(socket);
String msg;
while( !isInterrupted() && !"bye".equals( msg=s.getMessage()))
process(msg);
}
}
One important design consideration in OSGi is that the components keep working even if there are failures. In a network you often have transient errors that go away on their own. Even if they don't it is desirable that the server keeps on trying while you fix the problem. Your pseudo code would be a nightmare in practice since it would disappear on any error. Any system with multiple such components tends to becomes quickly unstable.
One thing that also surprised me is that you only support one connection at a time. In general it is better to not limit this and handle the messages in their own thread. In that case, you must ensure that each created handler for a connection is also closed appropriately.
Instantiate the ServerSocket outside (probably in the Activator) and pass it to the SocketListener via a constructor. You can call serverSocket.stop() in the stop function of the Activator than.
In case you call ServerSocket.stop() a SocketException will be thrown that is a subclass of IOException. Please think of handling IOException in the while iteration in the way that it will stop executing the iteration for sure.
You need to close that listening socket regardless of the message before exiting the thread function. Then what should really make a difference for you is calling setReuseAddress(true) on that socket to allow binding the port while old connection hangs in the timeout state.
And, please please please, use better indentation technique in your code ...
I got thread for server in my Android app and need to handle it properly when user decide to close it. I choose non-blocking ServerSocketChannel which accept() clients.
And got this
public class SocketServer extends Thread
{
private static final String LOG_TAG = "SocketServer";
private boolean isRunning = false;
private ServerSocketChannel listener = null;
public void _stop()
{
this.isRunning = false;
}
public void _start()
{
this.isRunning = true;
this.start();
}
private void free()
{
try
{
listener.close();
}
catch (IOException e)
{
//Error handle
}
listener = null;
}
public SocketServer(int port)
{
super();
try
{
listener = ServerSocketChannel.open();
listener.configureBlocking(false);
listener.socket().bind(new InetSocketAddress(port));
}
catch (IOException e)
{
//Error handle
}
}
public void run()
{
SocketChannel client = null;
while(isRunning)
{
try
{
client = listener.accept();//GC going mad
}
if(client != null)
Log.i(LOG_TAG, "ACCEPTED CLIENT");
catch (IOException e)
{
//Error handle
}
}
free();
}
All i'm doing is accepting new client - getting null because of no incoming connections and do it again until server is stopped.
ServerClient client is null at start and assigned to null by accept() if no connections available.
But Java's garbage collector thinks what client is somehow init by accept() or accept() somehow allocate some memory, which GC cleans after every while loop.
If comment accept() line (e.g do nothing) where will be no GC at all, so problem exactly in accept().
This quite not right in my opinion.
P.S. If there is some way to break blocking ServerSocket accept()/Socket read() state and exit properly, please tell me.
P.S. 2 Is it safe to write/ read to SocketChannel socket() as to Socket, will it block thread?
Many operations in Java create temporary objects internally to do their work.
You are much better off using a blocking SocketServer. This way the objects it creates is only on a per-accepted-Socket basis rather than a per-attempt basis.
I suggest you implement blocking NIO with a thread (or two) per connection first. If then you discover you have a performance issue with the number of threads you have, try using a Selector with non-blocking NIO.
The Application
I'm writing a client/server application in Java, that communicates by sending objects over sockets using the ObjectStream classes. Each node in the application looks approximately like this:
class Node {
SocketServer server;
Socket[] clients;
}
Here the server variable is the socket on which this node listens, and the client variables are the sockets on which other nodes listen, and to which this node sends objects.
The code that I use to write objects to one of the client sockets looks like this:
void sendMessage(Message<B, F> msg) throws IOException {
ObjectOutputStream writer = getWriter();
writer.writeObject(msg);
writer.flush();
}
private ObjectOutputStream writer;
ObjectOutputStream getWriter() throws IOException {
if (writer == null)
writer = new ObjectOutputStream(
new BufferedOutputStream(client.getOutputStream()));
return writer;
}
And the code that I use to handle connections and read objects from the node's server socket looks like this:
// the handler will listen for connections
final Thread handler = new Thread(new Runnable() {
public void run() {
try {
// create a new thread to handle the client
final Socket client = server.accept();
final Thread thread = new Thread(new Runnable() {
public void run() {
final ObjectInputStream reader;
try {
reader = new ObjectInputStream(client.getInputStream());
while (true) {
try {
val msg = reader.readObject();
messages.add((Message<B, F>) msg);
}
catch (EOFException e) {
// i noted it seemed to throw eofexceptions
}
catch (IOException e) {
// do something
}
}
}
catch (IOException e) {
// do something
}
}
});
thread.start();
} catch (IOException e) {
// do something
}
}
});
handler.start();
The Problem
I think I'm doing something wrong with the sockets here. Everything works fine when every server is only connected to a single client. However, when multiple clients are talking to the same server things go bad, and I get StreamCorruptedException's from the ObjectInputStream and other strange behaviour (putting in an instance of an UpdateRequest message, and getting out an instance of Integer(0) and some exceptions, for example.)
My intuition tells me that somehow the two object/byte streams are getting intermingled, and this produces the strange results when attempting to deserialize the objects. My question is: why is this happening aka what am I doing wrong, and how could I fix it?
You have an array of Sockets but you don't appear to have an array of writers and readers. So you're probably using the same writer and reader for all connections.
Really you should have a per-connection Connection object, that implements Runnable, and that has the Socket, the writer, and the reader as instance members.
Also when you catch EOFException you must break out of the loop and close the writer.
The problem was occurring due to messages being sent simultaneously, and this resulted in the bytes being mixed. The solution was to make sure that messages would only be received one at a time.