Creating a multi-user TCP server

J

jamesgoode

Hi,

I'm trying to create a multi-user TCP server, without the use of a
thread-per-connection model. My plan is to create an instance of the
ClientConnection class, which is stored in an array, for each
connection. A 'connection listener' thread handles this. The inputs
from the clients are then handled in a loop, which looks like this:

while (true)
{

for (int i = 0; i < MAX_CONNECTIONS; i++)
{
try {
if (connections!=null)
if (connections.in.ready())
connections.out.writeBytes(connections.in.readLine()+"\n
\r");
} catch (IOException e) {
// TODO Auto-generated catch block
connections = null;
}
}

}

(connections.in is a BufferedReader)

The problem is, that BufferedReader.ready() always seems to return
true, and that BufferedReader.readLine() halts the program until there
is a line to read.

All help is greatly appreciated.

Many thanks,

--James.
 
K

Knute Johnson

jamesgoode said:
Hi,

I'm trying to create a multi-user TCP server, without the use of a
thread-per-connection model. My plan is to create an instance of the
ClientConnection class, which is stored in an array, for each
connection. A 'connection listener' thread handles this. The inputs
from the clients are then handled in a loop, which looks like this:

while (true)
{

for (int i = 0; i < MAX_CONNECTIONS; i++)
{
try {
if (connections!=null)
if (connections.in.ready())
connections.out.writeBytes(connections.in.readLine()+"\n
\r");
} catch (IOException e) {
// TODO Auto-generated catch block
connections = null;
}
}

}

(connections.in is a BufferedReader)

The problem is, that BufferedReader.ready() always seems to return
true, and that BufferedReader.readLine() halts the program until there
is a line to read.

All help is greatly appreciated.

Many thanks,

--James.


BufferedReader.readLine() blocks until a line terminator is found in the
stream. That is going to be inconvenient for what you have planned. I
think it would be possible to check BufferedReader.ready() in a loop and
read a single char from the stream until ready() returns false, then
move on to your next stream. I don't see anything in the docs that
suggest that ready() will always return true like
InputStream.available() does. One advantage to this method is that it
should scale well with a ThreadPoolExecutor to a lot of connections.

Depending on what sort of latency you can tolerate you might be able to
just block on a read and set a short timeout. Or the other option is to
use NIO and its non-blocking features.

Are you sure that you are going to have so many simultaneous connections
that the thread per connection will be a problem? For a small number of
connections (less than 50 on a Windows machine) it is very easy to code.
 
J

jamesgoode

jamesgoode said:
I'm trying to create a multi-user TCP server, without the use of a
thread-per-connection model. My plan is to create an instance of the
ClientConnection class, which is stored in an array, for each
connection. A 'connection listener' thread handles this. The inputs
from the clients are then handled in a loop, which looks like this:
while (true)
{
for (int i = 0; i < MAX_CONNECTIONS; i++)
{
try {
if (connections!=null)
if (connections.in.ready())
connections.out.writeBytes(connections.in.readLine()+"\n
\r");
} catch (IOException e) {
// TODO Auto-generated catch block
connections = null;
}
}

(connections.in is a BufferedReader)

The problem is, that BufferedReader.ready() always seems to return
true, and that BufferedReader.readLine() halts the program until there
is a line to read.
All help is greatly appreciated.
Many thanks,

BufferedReader.readLine() blocks until a line terminator is found in the
stream. That is going to be inconvenient for what you have planned. I
think it would be possible to check BufferedReader.ready() in a loop and
read a single char from the stream until ready() returns false, then
move on to your next stream. I don't see anything in the docs that
suggest that ready() will always return true like
InputStream.available() does. One advantage to this method is that it
should scale well with a ThreadPoolExecutor to a lot of connections.

Depending on what sort of latency you can tolerate you might be able to
just block on a read and set a short timeout. Or the other option is to
use NIO and its non-blocking features.

Are you sure that you are going to have so many simultaneous connections
that the thread per connection will be a problem? For a small number of
connections (less than 50 on a Windows machine) it is very easy to code.


Thanks for your help,

I'll try what you've suggested, and incorporate it into the
ClientConnection class (just to make it easier).

I'll post back soon with results, and anything else that I'll have
found.

--James.
 
C

Christian

jamesgoode said:
Hi,

I'm trying to create a multi-user TCP server, without the use of a
thread-per-connection model.

I would recommend you to look a bit more into non Blocking IO .. there
is no way around this if you really don't want one Thread per Connection .

So you are gonna need to use a selector. And for Transforming bytes to
chars you have to use a Char(En/De)Coder.

For starting I found that rather intresting:
http://www.exampledepot.com/egs/java.nio/NbServer.html?l=rel

also the links on the page help with the other stuff involved in non
blocking IO.


Christian
 
E

EJP

Knute said:
BufferedReader.readLine() blocks until a line terminator is found in the
stream. That is going to be inconvenient for what you have planned. I
think it would be possible to check BufferedReader.ready() in a loop and
read a single char from the stream until ready() returns false, then
move on to your next stream. I don't see anything in the docs that
suggest that ready() will always return true like
InputStream.available() does.

Err, it doesn't return 'true', it returns an integer >= 0, which can
always be zero according to the contract, and always is e.g. in the case
of an SSLSocket. All that 'ready()' does ultimately is to return 'true'
if there is buffered data in the BufferedReader or available() > 0.

However there is no reason why ready() == true should mean there is an
entire line waiting to be read. So your readLine() can block.

So I would either overcome your phobia about threads, which are OK in
units of hundreds or so, or use NIO if you know you are going to have
tens or hundreds of thousands of connections. Mostly the blocking
threads arising out of normal use of java.net are doing nothing except
block.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,260
Messages
2,571,038
Members
48,768
Latest member
first4landlord

Latest Threads

Top