I modified the sample code available here for Client and Server My client :
public class Client {
public static void main(String[] args) {
int n=10000;
SocketTest [] st= new SocketTest[n];
for(int i=0;i<n;i++)
st[i]= new SocketTest("hi");
for(int i=0;i<n;i++)
new Thread(st[i]).start();
}
}
class SocketTest implements Runnable {
private String message = "";
private Selector selector;
private int i;
public SocketTest(String message){
this.message = message;
}
@Override
public void run() {
SocketChannel channel;
try {
selector = Selector.open();
channel = SocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_CONNECT);
channel.connect(new InetSocketAddress("127.0.0.1", 8511));
while (!Thread.currentThread().isInterrupted()){
selector.select();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()){
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid()) continue;
if (key.isConnectable()){
connect(key);
System.out.println("I am connected to the server");
}
if (key.isWritable()){
write(key);
}
if (key.isReadable()){
read(key);
}
}
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
close();
}
}
private void close(){
try {
selector.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void read (SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1000);
readBuffer.clear();
int length;
try{
length = channel.read(readBuffer);
} catch (IOException e){
System.out.println("Reading problem, closing connection");
key.cancel();
channel.close();
return;
}
if (length == -1){
System.out.println("Nothing was read from server");
channel.close();
key.cancel();
return;
}
readBuffer.flip();
byte[] buff = new byte[1024];
readBuffer.get(buff, 0, length);
//length=buff.length;
String fromserver = new String(buff,0,length,"UTF-8");
length = fromserver.length();
System.out.println("Server said: "+fromserver);
key.interestOps(SelectionKey.OP_WRITE);
}
private void write(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
i++;
message = "location now "+i;
try{
Thread.sleep(5000);
}
catch(InterruptedException ie)
{
System.out.println(""+ie);
}
channel.write(ByteBuffer.wrap(message.getBytes()));
// lets get ready to read.
key.interestOps(SelectionKey.OP_READ);
}
private void connect(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
try
{
if(!channel.finishConnect())
System.out.println("* Here *");
}
catch(ConnectException e)
{
System.out.println("BP 1");
e.printStackTrace();
//channel.close();
//key.cancel();
//return;
}
/*if (channel.isConnectionPending()){
while(!channel.ffinishConnect()){
System.out.println("not connected");
}
}*/
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_WRITE);
}
}
I create multiple clients on the same machine by creating multiple threads.
No of threads are determined by value of n.
When I run small no of clients I encounter no problem but as soon as I run with n as 500 i.e. 500 client threads , some threads run correctly but in some I encounter this :
java.net.ConnectException: Connection refused: no further information
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(Unknown Source)
at SocketTest.connect(Client.java:143)
at SocketTest.run(Client.java:61)
Line 143 is :
if(!channel.finishConnect())
So when I read documentation of this method it says it throws :
NoConnectionPendingException - If this channel is not connected and a connection operation has not been initiated.
ClosedChannelException - If this channel is closed.
AsynchronousCloseException - If another thread closes this channel while the connect operation is in progress.
ClosedByInterruptException - If another thread interrupts the current thread while the connect operation is in progress, thereby closing the channel and setting the current thread's interrupt status.
IOException - If some other I/O error occurs.
But the Exception is ConnectException. I tried catching it but it doesn't go into catch block.
Any help will be appreciated. Thanks. EDIT : I am working on windows. I tried changing value of n see how many client were created and how many caused exceptions and these are the results(I know waiting for more time after each test will allow for more open sockets as after each test scokets will be released after TIME_WAIT ) :
n clients connected(by keeping a count at server)
1000 522
2000 568
3000 626
4000 600 (maybe I gave less time before successive runs)
5000 1345
6000 1389
I am problemed by how can only these many clients are getting connected.
Can anyone please suggest better references to read for Client Server NIO.
EDIT 2
As EJP mentioned in his comment the window Backlog Queue was full. I modified Client code to generate 100 threads and then sleep for 5 seconds and this way there was not much load on Queue and most of the connection were successful(however still when making 10,000 connections some still failed).
ConnectException: Connection refused: 1) First try to ping the destination host, if the host is ping-able it means the client and server machine are in the network. 2) Try connecting to server host and port using telnet. If you are able to connect means something is wrong with your client code.
How do you handle Java net ConnectException connection refused? Ans: To resolve the Java net error, first try to ping the destination host, if you are able to ping the host means the client and server machine are in the proper network. Your next step should be connecting to the server host and port using telnet.
net. ConnectException: Connection refused: connect is the most frequent kind of occurring networking exception in Java whenever the software is in client-server architecture and trying to make a TCP connection from the client to the server.
ConnectException exception is one of the most common Java exceptions related to networking. We may encounter it when we're establishing a TCP connection from a client application to a server. As it's a checked exception, we should handle it properly in our code in a try-catch block.
ConnectException: connection refused
means nothing was listening at the IP:port you tried to connect to, or on some platforms that the server's listen-backlog queue filled up. If it is thrown and you catch it correctly, you will certainly catch it. You would have to expand on what actually happens and what your actual catch code looks like for further assistance.
However you have many other problems:
private void connect(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
try
{
if(!channel.finishConnect())
System.out.println("* Here *");
At this point, if finishConnect()
returned false, you should return. You should not fall through and re-register the channel for OP_WRITE.
The connection is still pending. Printing "* Here *"
is also pretty futile. Try printing something meaningful.
}
catch(ConnectException e)
{
System.out.println("BP 1");
e.printStackTrace();
//channel.close();
You should certainly close the channel at this point. It is of no further use to man or beast.
//key.cancel();
Closing the channel cancels the key. Remove wherever encountered.
//return;
As above, you should certainly return at this point.
}
/*if (channel.isConnectionPending()){
while(!channel.ffinishConnect()){
System.out.println("not connected");
}
}*/
Get rid of this crud. It is never appropriate to spin-loop in non-blocking mode. Don't even leave it lying around as comments: some idiot may come along later and play with putting it back.
channel.configureBlocking(false);
The channel is already in non-blocking mode. Otherwise you wouldn't be here. Remove.
channel.register(selector, SelectionKey.OP_WRITE);
Another way to do that is key.interestOps(SelectionKey.OP_WRITE);
Sleeping in networking code is literally a waste of time. It doesn't solve anything.
You are assuming that write()
succeeded completely, and you're ignoring the count it returns.
You're using a fairly poor quality reference:
write()
apply as above.flip()
is not 'like a reset'.ByteBuffer,
but in any case allocating a ByteBuffer
per read is poor practice.ServerSocketChannel.accept()
can return null.
Map
when keys have attachments.Thread.interrupted()
when NIO is interruptible anyway.IOException
on one channel.Try to find something better.
I believe the ConnectException
you are getting with 500 threads is not coming from SocketTest.connect()
. It could be coming from any of the other IO methods.
For a quick fix (and to convince yourself), you can explicitly catch ConnectException
in your main try-catch
block like this:
try {
// connect, write, and read ...
} catch (ConnectException ce) { // <-- catch the more specific Exception first
System.out.println("You caught a ConnectException.");
} catch (IOException e1) { // <-- you originally only caught this
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
As to why this is happening, I can tell you that I am currently ramping up to hundreds of threads for testing a SOAP service. I also get dropped connections all over the place, so maybe this is to be expected with such a large number of concurrent threads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With