views:

189

answers:

5

Is there a way to implement a socket server that services clients serially.
Generally the practice is to dispatch connected clients to a new thread that services requests and response however amounting to one thread per client on the server side.

I don't want to do this because I later want to port this app to Java ME that may have a limit on the number of concurrent threads running at a point of time.

I was wondering how to solve this problem?

+4  A: 

Sure, just don't fire off a background thread to handle the client.

EDIT

It seems like what you really want is for a large number of clients to be able to connect, but not create a load of threads. Since NIO doesn't appear to be supported how about using two threads:

  • One thread loops accepting connections, passing the connected Socket to the second thread which just adds it to a list of connected sockets (this needs to be synchronized)
  • A second thread which loops through its internal list of live connections, and does "some work" with each in turn.

Calling socket.setSoTimeout() with a reasonably small value should prevent the second thread waiting for too long on one connection.

Draemon
How do I handle request and responses, and what do I implement a mechanism when other clients want to connect. Will the server be able to push data to clients or will this facility be unavailable to it in this mechanism.
Kevin Boyd
You said you wanted to handle the connections serially - the other clients won't be able to connect. Isn't this what you wanted?
Draemon
I was under the impression that once you listen clients will queue up to the limit of the local tcp stack, and that using accept just pulls them off the stack. Other clients will be able to connect but will receive no data till the server processes everyone ahead of them.
Jherico
So what's the problem?
Draemon
Yes in way, Lets say there is Server S and three clients A, B and C.I want A, B and C all connected to S but being serviced in the same thread. I don't want thread's to build up in S per client. This way I could implement some sort of Server Push.
Kevin Boyd
What you're describing is NIO.
Draemon
So this means the second thread keeps polling the list of sockets and looks whether there is anything to read from those sockets, right? And suppose if it is reading socket A and data arrives at socket B will that be buffered or will it be lost?
Kevin Boyd
It will be buffered: see `Socket.setReceiveBufferSize()`. I assumed when you spoke of "server push" that the work would be writing rather than reading. Set the socket timeout to some small value and you won't spend too long waiting for A when B has data.
Draemon
I only have the following options in Java ME. KEEPALIVE, LINGER, SNDBUF, RCVBUF, or DELAY
Kevin Boyd
+1  A: 

Normally server handling looks something like this:

    ServerSocket s;
    Socket newSocket;
    while (newSocket = s.accept()) {
        new SocketHandlingThread(newSocket).start();
    }

where the SocketHandlingThread() is a class you created to do whatever the server side of the socket conversation should be.

There are two basic ways to do what you're asking (which is to handle the sockets synchronously). The first is to simply join on the handler thread before moving back on to accept() again, like this

    while (newSocket = s.accept()) {
        SocketHandlingThread thread = new SocketHandlingThread(newSocket);
        thread.start();
        thread.join();
    }

As pointed out in the comments below, you can avoid a join by just calling the thread's run method like so

 thread.run(); 

in place of the start and join calls.

The other method is to take whatever code is in the SocketHandlingThread's run method and move it into the loop directly.

Jherico
I think you mean thread.start() not thread.run(), and you can implement your second method by calling thread.run() - no need for thread.join()
Draemon
fixed errors pointed out.
Jherico
Join causes the calling process to wait till the thread you are joining on completes before returning. Its basically a 'wait till this other thing finishes' function.
Jherico
Can the server push data to clients in this way? Or will only one client be connected to the server at any point of time. I have given a A,B,C example to Draemon.
Kevin Boyd
it sounds like what you want is a pool of threads each handling X clients and using Polling to determine whether there's any traffic to transfer for a given socket.
Jherico
I don't know what its called though, any way of implementing connection pooling?
Kevin Boyd
+1  A: 

You could use non-blocking sockets. If you do this, then you don't need a thread for each client. Java has supported this for a while now via NIO. I'm not sure if this is supported by Java ME. Java ME is growing up these days such that it includes many of the features of JSE. It is probably a little unusual that you have server-side functionality in a Java ME environment that needs to service many client connections.

In your situation, is the traffic still not routed through a server? If so, there is no reason that the J2ME environment cannot receive messages from many other clients or peers (if you want to call them that) via a single socket connection to the server.

Todd Stout
For a p2p chat application I need to implement this mechanism. Sorry to say that J2ME does not support NIO.
Kevin Boyd
There is no server in this case one phone is acting as the server.
Kevin Boyd
How do your clients discover the ip address and port of the phone?
Todd Stout
Unless you are operating your own private net for phones, I don't see how you can truly host a TCP/UDP server that is publicly routable, without having a server in the middle.
Todd Stout
@Todd: All phones are connected to a WLAN network.
Kevin Boyd
A WLAN that you control...you could introduce a server in the middle using whatever tech you wanted...right? In this case your server would not be constrained by JME.
Todd Stout
I can't right now I have some constraints on that, The only way I can work with is phones, I can't involve a pc.
Kevin Boyd
Can you elaborate on the constraints?
Todd Stout
Constraints is I only have to work with phones connected to WLAN access point, are you saying that I should contact a server over the internet or something on those lines and that acts like a Manager of all these client.
Kevin Boyd
I assume you are building a private p2p network right?
Todd Stout
I'm suggesting that you introduce a server within your private net that routes messages between each phone. This way the server can deal with all the threading issues and need not be concerned with the limitations of JME. An ancient PC could handle a few hundred phones if the server were designed right using non-blocking sockets supported by Java's NIO.
Todd Stout
This brings up another question...how far do you need to scale? Do you have 10, 20, 100, or 10000 phones connected to each other?
Todd Stout
10 phones connected to one
Kevin Boyd
Clients may vary from 3 to 10, what kind of workaround are you hinting at?
Kevin Boyd
The workaround involves not using threads. I'm not convinced your problem needs a workaround yet. Where does the 3 to 10 number come from. Do you expect that to change?
Todd Stout
Okay lets say I can fix the number to 5, is there a workaround?
Kevin Boyd
+1  A: 

You can set a SO_TIMEOUT on your accepting socket. This will force the accept call to be non-blocking. That way you can wait for a little bit of time, then serve one of the previously accepted connections, then back to accepting new ones, and so on and so forth. The code would vaguely look like this:

do(
  try{
    socket.setSoTimeout(200);
    Socket connected = socket.accept()
  } catch (SocketTimeoutException e){//just ignore}
  //handle your other threads/connections here
} while (!shutDown)
mlaverd
Could you elaborate a bit?
Kevin Boyd
Added code to the original post to illustrate
mlaverd
+1  A: 

There is a great example of server side socket handling including pooling that can be found here.

However consider that you might not actually need pooling - I have had no problem serving 800 simultaneous clients from one server each with their own dedicated socket thread.

Pool
Will check out the link, wow 800 threads seems quite good, the issue here is I want to port the code to Java ME and it may have issues with even 5 concurrent threads. I'm trying to play safe here with all the phone stuff.
Kevin Boyd
Ah, sorry, I thought you meant you had many ME clients connecting to a server which you had control of. A quick Google of minimum supported threads on ME found the following: http://discussion.forum.nokia.com/forum/showthread.php?t=79232 Have you thought of passing all communication through a central server? I would have thought it would have to be done that way due to sandbox restrictions but it's a long time since I've touched Java ME!
Pool
I had given it a thought but for now I can't go through with that implementation, many thanks for the link that was very useful indeed, it gives me some leads on what new docs to dig out and check for new thread specs. Well there are some limitations to the J2ME platform but it has improved a lot. Wish I could give you +2. Cheers!
Kevin Boyd