Why my non blocking Java server refuses client connections? - java

Good day everybody! I'm developing NIO based server and I'm trying to test it with simple client programm.
Before posting code I would like to briefly describe problem: in the test case where server does his job immediately everything is OK. But when I'm trying to add some real life behavior such as short delay on servicing I'm getting "java.net.ConnectException: Connection refused" exceptions. More precisely, part of 100 client threads get this connection refused exception.
I use the following code:
Client
public class TCPClient implements Runnable{
private String name;
public TCPClient(String name)
{
this.name = name;
}
public static void main(String[] args)
{
for(int i=0;i<100;i++)
{
Thread t = new Thread(new TCPClient("thread # "+Integer.toString(i)));
t.start();
}
}
#Override
public void run()
{
Socket socket = null;
OutputStream out = null;
int counter = 0;
try
{
socket = new Socket();
socket.connect(new InetSocketAddress("192.168.3.109",2345), 0);
out = socket.getOutputStream();
byte[] bytes;
while(counter<100)
{
counter++;
bytes = (name+ ", message # "+Integer.toString(counter)+System.lineSeparator()).getBytes();
out.write(bytes);
out.flush();
Thread.sleep(200);
}
}
catch(Exception ex)
{
System.out.println(name+" "+Integer.toString(counter));
ex.printStackTrace(new PrintStream(System.out));
System.out.println();
}
finally
{
if(socket!=null && out!=null)
{
try
{
socket.close();
out.close();
}
catch(Exception ex)
{
System.out.println("client close error");
}
}
}
}
}
Server
public class TCPServer {
private Selector selector;
private boolean isRunning;
private ServerSocketChannel server;
private int counter;
private PrintWriter times;
private PrintWriter logger;
private Charset charset;
private CharsetDecoder decoder;
ByteBuffer bb;
long serviceTime,curTime;
Random random;
public TCPServer(int port)
{
counter = 0;
isRunning = false;
serviceTime = 0;
random = new Random();
random.setSeed(System.currentTimeMillis());
bb = ByteBuffer.allocate(2048);
try
{
selector = Selector.open();
server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(port));
server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);
}
catch(Exception ex)
{
System.out.println("initialization error "+ex.getMessage());
}
}
public void startServer() {
isRunning = true;
int acc = 0;
boolean error = false;
while (isRunning) {
try
{
selector.select();
Set keys = selector.selectedKeys();
Iterator it = keys.iterator();
while(it.hasNext())
{
SelectionKey key = (SelectionKey)it.next();
if (key.isConnectable())
{
((SocketChannel)key.channel()).finishConnect();
}
if (key.isAcceptable())
{
//logger.println("socket accepted");
//logger.flush();
acc++;
System.out.println("accepted sockets count = "+acc);
SocketChannel client = server.accept();
client.configureBlocking(false);
client.socket().setTcpNoDelay(true);
client.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable())
{
curTime = System.currentTimeMillis();
SocketChannel sc = (SocketChannel) key.channel();
bb.clear();
int x = sc.read(bb);
if(x==-1)
{
key.cancel();
continue;
}
counter++;
// Thread.sleep(2);
int sum=0;
for(int dummy=0;dummy<4000000;dummy++) // without this delay client works fine
{
sum+=random.nextInt();
sum%=1005;
}
serviceTime+= System.currentTimeMillis() - curTime;
if(counter>=10000)
{
System.out.println("recieved messages count = "+counter);
System.out.println("service time = "+serviceTime+" milliseconds");
}
}
}
keys.clear();
}
catch (Exception ex)
{
System.out.println("error in recieving messages "+ex.getMessage());
}
}
}
public static void main(String[] args)
{
TCPServer deviceServer = new TCPServer(2345);
deviceServer.startServer();
}
}
The problem is in for(dummy...) loop - it's just simulation of service delay - time needed to parse incoming messages, write something to DB and so on. When delay is small code works fine, all of 10000 messages come to server (100 client threads X 100 messages from each client) but when dummy loop makes over 3.000.000 iterations some of client threads fail to connect to server. One more strange thing here is ignoring infinite timeout property by client socket. I mean socket.connect(InetAddress,timeout) with timeout equal to zero means infinite timeout - in other words service delay doesn't make sense at least I expect such behavior.

It looks like the server socket has a maximum number of pending connections it will allow. The JavaDoc for ServerSocket says:
The maximum queue length for incoming connection indications (a
request to connect) is set to 50. If a connection indication arrives
when the queue is full, the connection is refused.
Right now, I can't find the same information for ServerSocketChannel, but I'm sure it must exist.
ServerSocketChannel.bind allows configuration of the number of pending connections allowed.

Related

Java NIO Selector doesn't work when not using localhost

I've been working on a program that uses networking with Java that uses the NIO Selector following this tutorial and for some reason when I try to test the program with my friends (that are far away in another network) it doesn't work,
even though when I try to test it myself on only my computer it works perfectly.
Here is the relevant code for the question:
Class EchoServer (a Thread):
private Selector selector;
private ServerSocketChannel serverSocket;
private boolean stop = false;
private List<String> pendingStrings;
public EchoServer() throws IOException {
// Get selector
this.selector = Selector.open();
System.out.println("Selector open: " + selector.isOpen());
// Get server socket channel and register with selector
this.serverSocket = ServerSocketChannel.open();
InetSocketAddress hostAddress = new InetSocketAddress("", NetworkingSettings.PORT);
serverSocket.bind(hostAddress);
serverSocket.configur eBlocking(false);
int ops = serverSocket.validOps();
SelectionKey selectKy = serverSocket.register(selector, ops, null);
this.pendingStrings = new ArrayList<>();
}
#Override
public void run() {
while (!stop) {
try {
update();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void update() throws IOException {
System.out.println("Waiting for select...");
int noOfKeys = selector.select();
System.out.println("Number of selected keys: " + noOfKeys);
Set selectedKeys = selector.selectedKeys();
Iterator iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey ky = (SelectionKey) iter.next();
if (ky.isAcceptable()) {
acceptClient();
}
else if (ky.isReadable()) {
readDataFromClient(ky);
}
iter.remove();
}
}
Class EchoClient:
private SocketChannel client;
private InetSocketAddress hostAddress;
private boolean connected;
public EchoClient(String ip) {
this.hostAddress = new InetSocketAddress(ip, NetworkingSettings.PORT);
connected = false;
}
public void connect() throws IOException {
if (!connected) {
client = SocketChannel.open(hostAddress);
connected = true;
}
}
public void sendMessage(String message) throws IOException {
try {
byte[] messageBytes = message.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(messageBytes);
client.write(buffer);
buffer.clear();
} catch (IOException e) {
cleanUp();
}
}
Now, it seems that the problem is in the server because I can't even connect to the server when my friend runs it (and I am the client).
I suspect the source of the problem are those lines in EchoServer:
InetSocketAddress hostAddress = new InetSocketAddress("", NetworkingSettings.PORT);
serverSocket.bind(hostAddress);
But I can't seem to figure out what is it.
Important Note:NetworkingSettings.PORT is 80, I know it's a port used for http and maybe that is the problem, but I really want to avoid needing to use port forwarding and firewall settings.
The problem lies with the InetSocketAddress the ServerSocketChannel binds to. To allow connections on both localhost and remote network interfaces, you need to bind to the wildcard address. This is done by using the InetSocketAddress constructor that only takes a port number:
InetSocketAddress hostAddress = new InetSocketAddress(NetworkingSettings.PORT);

Socket Programming - Java - Not receiving some messages

I just started working on Sockets with both client and server threads in the same Node. Below is my code structure -
I have a Node class which makes connections to different Nodes. It sends REQUEST messages to the Nodes and waits till it gets REPLY from all the nodes tracked using the outstandingreplies variable which is static and volatile, also has synchronised getters and setters.
Server Class spawns Processor thread which processes each message that it hears.
It modifies certain variables which furthers the code execution. On getting a REPLY message, it decrements outstandingreplies variable. It also sends messages to node which just sent the messages based on certain conditions.
Below is my code, I have removed certain details.
Node Class
// Creates connections to other Nodes(machines) and sends messages
public class Node {
public static volatile int timestamp = 0;
public static volatile int highestTimestamp = 0;
public static int csCounter = 0;
public static int nodeId;
public static int n;
public static String[] hosts;
public static int[] ports;
public static volatile int[] deferredNodes;
public static volatile boolean requestingCS = false;
public static volatile int outstandingReplies;
// skipping getters and setters for variables shared between server and client threads
// method to connect the node with other nodes
public static Connection connect() {
// skipping standar code to create sockets
}
public static void main(String[] args) {
// start the receiver
Server server = new Server();
server.start();
// make the connections with other nodes
Connection connections = connect();
while (counter <= 2) {
// create a message
Message message = new Message(); // skipping details to create a msg
// send requests to all other nodes
for (int i = 0; i < n; i++) {
if (i != nodeId) {
System.out.println("Sending message " + message + " to node " + i);
try {
connections.outs[i].writeObject(message);
outstandingReplies++;
} catch (Exception e) {
e.printStackTrace();
}
}
}
// All REQUEST messages sent, WAIT for all replies
while (outstandingReplies != 0) {
// System.out.println("Waiting for replies");
}
// send REPLY msg based on some logic
if(logic is true){
// send messages to other nodes
Message replyMessage = new Message("REPLY", timestamp, nodeId);
try {
connections.outs[i].writeObject(replyMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Connections Class
// Stores all the connections created by the Node Class
Server Class
// Listens to requests from nodesand spawns a Processor thread for each socket
public class Server extends Thread {
#Override
public void run() {
try {
System.out.println("Starting the node's receiver thread");
// create a serversocket to listen to requests
ServerSocket serverSocket = new ServerSocket(Node.ports[Node.nodeId]);
for (int i = 0; i < Node.n - 1; i++) {
System.out.println("Opening sockets");
Socket socket = serverSocket.accept();
// create a processor thread for each to read and process the incoming Messages
Processor processor = new Processor(socket);
System.out.println("Starting message processor");
processor.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Processor Class
// Processes the messages and sends reply when needed
public class Processor extends Thread {
Socket socket;
int[] replies = new int[10];
public Processor(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(
socket.getOutputStream());
while (true) {
System.out.println("Waiting for msg");
System.out.println("Socket is " + socket.isConnected());
Message message = (Message) in.readObject();
Node.timestamp = Math.max(Node.timestamp + 1, message.timestamp);
// printing the queue here
System.out.println("Processor received " + message);
// if message is a request
if (message.type.trim().equals("REQUEST")) {
if(condition is true){
// do something
} else {
// send reply to node who sent you message
Message replyMessage = new Message("REPLY", Node.timestamp,
Node.nodeId);
System.out.println(
"Send " + replyMessage + " to " + Node.hosts[message.nodeId]);
out.writeObject(replyMessage);
}
}
if (message.type.trim().equals("REPLY")) {
// do something
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
I run this code on two machines. The connections are established successfully and some messages are exchanged. However, in some cases the Processor class does not get message even when the socket is still connected.
I did go through some questions on missing messages with Java sockets which mentioned that when nodes gets two messages at once, it processes only the first message and the second message is buffered. I am not sure how I can check if that is the case with my code.
I am guessing something is wrong with I am handling sockets. Would really help if anyone could point where I am doing things incorrectly.
TIA

HTTP1.1 Connection:keepalive implement with java occurs withjava.net.SocketTimeoutException: Read timed out

I'm implement a http server with version1.1 using java socket programming. I use a version 1.0 sample code and I want add the persistent connection feature by not closing socket utilt a "Connection : close" send to the server. However, I came accross with "java.net.SocketTimeoutException: Read timed out" info after an input like"localhost:8080/xxxx" on my browser and not receiving anything when tested with a client program. Code is too long, and I mention the matter parts bellow! Can you find the problems for me, thanks!!!
////////here is the server part using thread pool techs
//Webserver class
protected static Properties props = new Properties();
/* Where worker threads stand idle */
static Vector threads = new Vector();
public static void main(String[] a) throws Exception {
int port = 8080;
if (a.length > 0) {
port = Integer.parseInt(a[0]);
}
loadProps();
printProps();
/* start worker threads */
for (int i = 0; i < workers; ++i) {
Worker w = new Worker();
(new Thread(w, "worker #"+i)).start();
threads.addElement(w);
}
ServerSocket ss = new ServerSocket(port);
while (true) {
Socket s = ss.accept();
Worker w = null;
synchronized (threads) {
if (threads.isEmpty()) {
Worker ws = new Worker();
ws.setSocket(s);
(new Thread(ws, "additional worker")).start();
} else {
w = (Worker) threads.elementAt(0);
threads.removeElementAt(0);
w.setSocket(s);
}
}
}
}
//Worker class inherit from Webserver class
byte[] buf;
Worker() {
buf = new byte[BUF_SIZE];
s = null;
}
synchronized void setSocket(Socket s) {
this.s = s;
notify();
}
public synchronized void run() {
while(true) {
if (s == null) {
/* nothing to do */
try {
wait();
} catch (InterruptedException e) {
/* should not happen */
continue;
}
}
try {
handleClient();
} catch (Exception e) {
e.printStackTrace();
}
/* go back in wait queue if there's fewer
* than numHandler connections.
*/
if(!headAttri.getPersistConnec())
s = null;
//
Vector pool = WebServer.threads;
synchronized (pool) {
if (pool.size() >= WebServer.workers) {
/* too many threads, exit this one */
try{
if(s != null)
s.close();
}catch (IOException e) {
e.printStackTrace();
}
return;
} else {
if(!headAttri.getPersistConnec())
pool.addElement(this);
}
}
}
}
//in handle client I mention the socket handles here(s is the socket)
void handleClient() throws IOException {
//...
s.setSoTimeout(WebServer.timeout);
s.setTcpNoDelay(true);
//...
try{
//...handle request and response the client
//...
}finally{
//close socket if head info "Connection: close" is found
if(headAttri.getPersistConnec()){
s.setKeepAlive(true);
}
else{
s.close();
}
}
}
//////////end server part
//////here is the client part
public SimpleSocketClient()
{
String testServerName = "localhost";
int port = 8080;
try
{
// open a socket
Socket socket = openSocket(testServerName, port);
// write-to, and read-from the socket.
// in this case just write a simple command to a web server.
String result = writeToAndReadFromSocket(socket, request_str[1]);
// print out the result we got back from the server
System.out.println(result);
// close the socket, and we're done
socket.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private Socket openSocket(String server, int port) throws Exception
{
Socket socket;
// create a socket with a timeout
try
{
InetAddress inteAddress = InetAddress.getByName(server);
SocketAddress socketAddress = new InetSocketAddress(inteAddress, port);
// create a socket
socket = new Socket();
// this method will block no more than timeout ms.
int timeoutInMs = 10*1000; // 10 seconds
socket.connect(socketAddress, timeoutInMs);
return socket;
}
catch (SocketTimeoutException ste)
{
System.err.println("Timed out waiting for the socket.");
ste.printStackTrace();
throw ste;
}
}
private String writeToAndReadFromSocket(Socket socket, String writeTo) throws Exception
{
try
{
// write text to the socket
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write(writeTo);
bufferedWriter.flush();
//test
//bufferedWriter.write("GET src/WebServer.java HTTP/1.1\r\nHost: localhost\r\nConnection: close");
//bufferedWriter.flush();
// read text from the socket
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder sb = new StringBuilder();
//string handling code
String str;
while ((str = bufferedReader.readLine()) != null)
{
sb.append(str + "\n");
}
// close the reader, and return the results as a String
bufferedReader.close();
return sb.toString();
}
catch (IOException e)
{
e.printStackTrace();
throw e;
}
}
////end client part
//close socket if head info "Connection: close" is found
if(headAttri.getPersistConnec()){
s.setKeepAlive(true);
It is hard to tell from your code what you are really doing but based on this code fragment it looks like you are mixing up HTTP keep alive (i.e. Connection: keep-alive handling, multiple requests in a single TCP connection) with TCP keep alive (detect broken TCP connection). See Relation between HTTP Keep Alive duration and TCP timeout duration and HTTP Keep Alive and TCP keep alive for explanations about the difference.
I want add the persistent connection feature by not closing socket utilt a "Connection : close" send to the server
That's not how you do it. You have to close the connection yourself, either
after a request with a Connection: close header is received and you've sent the response, or
when you get a read timeout on the socket reading the next request.
The length of the read timeout is entirely up to you, because it is up to you to protect yourself from DOS attacks among other things.
NB calling Socket.setKeepAlive(true) has absolutely nothing whatsoever to do with it.
NB 2 You should look into java.util.concurrent.Executor rather than implement your own thread pool.

Multithreading Thread restart

i'am writing a small app to remote control a (Behringer x32) Mixing console. And i got a problem with the communication.
I'am sending data from the pc (app) to the console (port 10023 UDP Protocol), then the console answers to the port from the pc has send data, (random port).
So i have 2 Threads one for sending data, and one for listening for data from the console..... so every time i send data to the console, i need to change the listening port... so i have to kill the listening thread and start it new.
But after some time a have and the app has about x1000 threads open.
How can i restart the Thread or update the listening port without create a new thread?
here's the code for this section, the whole files are # gihub
the listening thread class:
public class Receiver implements Runnable {
private List<IReceiverListener> listeners;
private final static int PACKETSIZE = 48;
private int port;
public Receiver() {
listeners = new ArrayList();
}
public void addReceiverListener(IReceiverListener listener) {
listeners.add(listener);
}
private void update(String data, String adress) {
for (IReceiverListener listener : listeners) {
listener.receiveConsoleData(data, adress);
if (data.indexOf("active") > -1) {
listener.incrementWatchDog();
}
}
}
#Override
public void run() {
try {
// Convert the argument to ensure that is it valid
// Construct the socket
while (true) {
//System.out.println("Listen on Port:" + this.port);
DatagramSocket socket = new DatagramSocket(this.port);
// Create a packet
DatagramPacket packet = new DatagramPacket(new byte[PACKETSIZE], PACKETSIZE);
// Receive a packet (blocking)
socket.receive(packet);
// Print the packet
update(new String(packet.getData()), packet.getAddress().toString());
//logger.addLogData(new String(packet.getData())+" "+packet.getAddress().toString());
// Return the packet to the sender
socket.close();
}
} catch (IOException e) {
}
}
public void setPort(int port) {
this.port = port;
}
public int getPort() {
return port;
}
}
and here my port updateFunction
#Override
public void updatePort(int port) {
receiverThread.interrupt();
receiverThread = null;
receiver.setPort(port);
receiverThread = new Thread(receiver);
receiverThread.start();
}
and the sending thread does this, when it sends data:
listener.updatePort(dsocket.getLocalPort());
This is actually not a threading problem. The problem is, that the receiver thread is stuck in the receive method, so it cannot react to the changed port. However, calling the method DatagramSocket#close from another thread releases the blocking receiver thread with a SocketException.
Thus, you can solve this by closing the currently receiving socket when the receiving port was changed. The receiving thread can now catch the SocketException and create a new DatagramSocket that listens on the new port.
There is no need to kill and recreate threads.
First you put the socket into a field. This allows you to access it from another thread, so you can call the socket.close() method. Second, you put another try-catch block into the while(true) loop, which only catches SocketException.
Something like this might work fine:
public class Receiver implements Runnable {
private static final int PACKETSIZE = 48;
private final ConcurrentLinkedQueue<IReceiverListener> listeners = new ConcurrentLinkedQueue<>();
private volatile DatagramSocket socket;
private volatile int port;
public Receiver(int port) {
this.port = port;
}
public void addReceiverListener(IReceiverListener listener) {
listeners.add(listener);
}
public void updatePort(int port) {
this.port = port;
DatagramSocket socket = this.socket;
if (socket != null) {
socket.close();
}
}
#Override
public void run() {
try {
while (true) {
receiveLoop(new DatagramSocket(port));
}
} catch (IOException e) {
// handle error
}
}
private void receiveLoop(DatagramSocket newSocket) throws IOException {
try (DatagramSocket socket = newSocket) {
this.socket = newSocket;
while (true) {
DatagramPacket packet = new DatagramPacket(new byte[PACKETSIZE], PACKETSIZE);
socket.receive(packet);
process(packet);
}
} catch (SocketException e) {
// port was changed -> return and restart with a new socket
} finally {
this.socket = null;
}
}
private void process(DatagramPacket packet) {
update(new String(packet.getData()), packet.getAddress().toString());
}
private void update(String data, String adress) {
for (IReceiverListener listener : listeners) {
listener.receiveConsoleData(data, adress);
if (data.indexOf("active") > -1) {
listener.incrementWatchDog();
}
}
}
}
Please note, that this might still contains some bugs. It is only supposed to give you a rough idea of how to solve this.
As you are using DatagramSocket, you can change the used port by Binding the socket to a new port rather than the used one:
socket.bind(new InetSocketAddress(new_port));
But remember that bind() method won't work unless the socket is already opened and a port assigned to it, so at the first time you have to create the socket regularly, then when you try to change the port, just bind it.
And the following is a complete visualization of the process:
public void video_udp_server(int port) throws Exception
{
byte[] receiveData = new byte[Integer.MAX_VALUE/100];
for(int i = 0; i < receiveData.length; i++){
receiveData[i] = ' ';
}
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
DatagramSocket socket = null;
try{
socket = new DatagramSocket(port);
}catch(Exception ex){
socket.bind(new InetSocketAddress(port));
}
socket.setReuseAddress(true);
socket.receive(receivePacket);
System.out.println(new String(receivePacket.getData()));
}

java.net.ConnectException: Connection timed out: no further information

Now today I was testing Server and Client code on different machine.
Both were on same Wi-fi network.
I created clients using below code and got this exception for many threads :
java.net.ConnectException: Connection timed out: no further information
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(Unknown Source)
at SocketTest.connect(Client.java:188)
at SocketTest.run(Client.java:73)
at java.lang.Thread.run(Unknown Source)
the line 73 is connect(key)
and line 188 is if(!(channel.finishConnect()))
So the client thread was unable to connect because no reply came from server ? Right ?
Question)When I run both Server and Client on same machine localhost this exception does not arise. What may be the reasons ? (network problem ?).
Also I also use Backlog queue parameter in public void bind(SocketAddress endpoint,int backlog) as 2000. While exact size is unknown(around 200 ?) but I am using a large value so that maximum value will be used.(Right ? or Java will make a queue ?).
Can this be a reason : The Server puts the request in backlog queue and till it gets time to serve it, the timeout may have happened at Client ?
Client :
public class Client {
public static void main(String[] args) {
int n=100;
SocketTest [] st= new SocketTest[n];
for(int i=0;i<n;i++)
st[i]= new SocketTest("hi");
for(int i=0;i<n;i++)
{
if(i%50 == 0)
try{
Thread.sleep(5000);
}
catch(InterruptedException ie)
{
System.out.println(""+ie);
}
new Thread(st[i]).start();
}
}
}
class SocketTest implements Runnable {
private String message = "";
ByteBuffer readBuffer = ByteBuffer.allocate(1000);
private Selector selector;
private int i;
public static AtomicInteger cnt= new AtomicInteger(0);
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("192.168.1.10", 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(ClosedByInterruptException e)
{
// let go of thread
}
catch(CancelledKeyException e){
e.printStackTrace();
}
catch (IOException e1) {
System.out.println("IOE Occured|maybe Server died");
e1.printStackTrace();
} finally {
close();
}
}
private void close(){
try {
if(selector!=null)
selector.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void read (SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
readBuffer.clear();
int length;
try{
length = channel.read(readBuffer);
} catch (IOException e){
System.out.println("Reading problem, closing connection for : "+channel.getLocalAddress());
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;
if(i==2)
{
cnt.addAndGet(1);
System.out.println("****"+cnt.get()+"****");
}
try{
Thread.sleep(5000);
}
catch(InterruptedException ie)
{
System.out.println(""+ie);
//Thread.currentThread().interrupt();
}
//assuming all goes in one shot
channel.write(ByteBuffer.wrap(message.getBytes()));
key.interestOps(SelectionKey.OP_READ/*|SelectionKey.OP_WRITE*/);
}
private void connect(SelectionKey key){
SocketChannel channel= (SocketChannel) key.channel();
try
{
if(!(channel.finishConnect())){
//System.out.println("* Here *");
return;
}
}
catch(ConnectException e){
System.out.println("Conect Exception");
e.printStackTrace();
try{channel.close();}
catch(IOException ie){ie.printStackTrace();key.cancel();return;}
return;
}
catch(IOException e)
{
System.out.println("BP 1"+e);
e.printStackTrace();
try{channel.close();}
catch(IOException ie){ie.printStackTrace();key.cancel();return;}
return;
}
//channel.configureBlocking(false);
//channel.register(selector, SelectionKey.OP_WRITE);
key.interestOps(SelectionKey.OP_WRITE);
}
}
The connect timed out because the server didn't reply.
When I run both Server and Client on same machine localhost this exception does not arise. What may be the reasons ? (network problem ?).
Why should it arise? The server is there, the client is there, no network problems in between. The question doesn't make sense.
Also I also use Backlog queue parameter in public void bind(SocketAddress endpoint,int backlog) as 2000. While exact size is unknown(around 200 ?) but I am using a large value so that maximum value will be used. Right?
Right.
or Java will make a queue?
I don't know what this means. Java doesn't do anything with the backlog parameter. It goes straight to TCP.
Can this be a reason: The Server puts the request in backlog queue and till it gets time to serve it, the timeout may have happened at Client ?
No. Only completed connections go on the backlog queue.

Categories