dcsimg
A server based on Selector and SocketChannel is not notified of the closure of a client if the closure follows a write operation too quickly.
1 posts in topic
Flat View  Flat View
TOPIC ACTIONS:
 

Posted By:   cristiano_saturni
Posted On:   Monday, July 22, 2002 03:37 AM

Dear friends, I've written a server using the nio SocketChannels. A Selector is registered with a ServerSocketChannel (to be notified for OP_ACCEPT) and a SocketChannel ( to be notified for OP_READ). I have the following problem. When a client connects to the server, writes and closes, the Selector is only notified for 1 OP_CONNECT and 1 OP_READ instead 1 OP_CONNECT and 2 OP_READ. While when a client connects to the server, writes, waits 50ms and closes, the Selector behaves properly. It seems that the selector compacts two consecutive OP_READ notifications in 1 and loses the closure of the client. Can anyone tell me where Im wrong? The code is the following. Th   More>>

Dear friends,



I've written a server using the nio SocketChannels.



A Selector is registered with a ServerSocketChannel (to be notified for OP_ACCEPT) and a SocketChannel ( to be notified for OP_READ).



I have the following problem.



When a client connects to the server, writes and closes, the Selector is only notified for 1 OP_CONNECT and 1 OP_READ instead 1 OP_CONNECT and 2 OP_READ.



While when a client connects to the server, writes, waits 50ms and closes, the Selector behaves properly.



It seems that the selector compacts two consecutive OP_READ notifications in 1 and loses the closure of the client.



Can anyone tell me where Im wrong?



The code is the following.



Thanks.



Bye



CRI




			


//*********** BEGIN CLIENT *********


import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.io.*;
import java.nio.channels.spi.*;
import java.nio.charset.*;
import java.lang.*;


public class CClient
{
public static void connect() throws Exception
{
String str="ciao";
ByteBuffer buffer = ByteBuffer.allocateDirect(4);
buffer=ByteBuffer.wrap(str.getBytes());

SocketChannel client = SocketChannel.open();
client.configureBlocking(true); // Non-blocking

client.connect(new InetSocketAddress(InetAddress.getLocalHost(),2222));
System.out.println("connected.");

int nBytes = client.write(buffer);

System.out.println("wrote "+str+" i.e "+nBytes+" bytes.");

// Thread.sleep(500); // With this line it works. Without it doesnt !!! Help.

client.close();

System.out.println("closed");
}


public static void main(String args[])
{
try
{
connect();
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}


//*********** END CLIENT ***********

//*********** BEGIN SERVER *********
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.nio.charset.*;
import java.lang.*;


public class SServer
{
public void startServer() throws Exception
{
int port = 2222;
Selector sel = Selector.open();

ServerSocketChannel server = ServerSocketChannel.open();
server.configureBlocking(false);
server.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),port));

server.register(sel, SelectionKey.OP_ACCEPT );

System.out.println("Server started...");

while(true)
{
System.out.println("
selecting..");

sel.select();

Set readyKeys = sel.selectedKeys();

Iterator it = readyKeys.iterator();
while (it.hasNext())
{
SelectionKey key = (SelectionKey)it.next();
it.remove();

System.out.println("begin key..");

if (key.isAcceptable())
{
System.out.println("-------- client accepted.");

SocketChannel socket = server.accept();
socket.configureBlocking(false);
socket.register(sel,SelectionKey.OP_READ);
}
else
{

System.out.println("reading...");

SocketChannel socket=(SocketChannel)key.channel();

int nBytes = 0;
ByteBuffer buffer = ByteBuffer.allocateDirect(4);
nBytes = socket.read(buffer);

System.out.println("read "+nBytes+" bytes.");

if(nBytes <0)// client has closed
{

System.out.println("++++++++ client closed.");

socket.close();
// key.cancel(); // not necessary
}
else
{
System.out.println("******** client wrote = "+buffToString(buffer));
}

System.out.println("end key.");
}
}
}
}


public static String buffToString(ByteBuffer buffer)
{
String result=null;
try
{
buffer.flip();

Charset charset = Charset.forName( "us-ascii" );
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode( buffer );
result= charBuffer.toString();
}
catch(CharacterCodingException e)
{
System.out.println(e.toString());
}
return result;
}

public static void main(String args[])
{
SServer nb = new SServer();
try
{
nb.startServer();

}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}

//*********** END SERVER ***********
   <<Less

Re: A server based on Selector and SocketChannel is not notified of the closure of a client if the closure follows a write operation too quickly.

Posted By:   Charles_Dickens  
Posted On:   Thursday, July 25, 2002 01:04 AM

Hi,

what about of using different selectors?! Try to use different selectors for registration of OP_READ, OP_ACCEPT and OP_WRITE events. Of course you have to add more loops,but it's worth a try, perhaps it works!
About | Sitemap | Contact