java close problem

Calin Vaida calinv at gmail.com
Wed Apr 16 17:59:15 UTC 2008


Hi guys,

I am not sure if this is the proper list to write but I decided to write
here because my problem involve FreeBSD and Java.
So, I am working on a project that involves networking between a client and
a server and I have a problem with close operations.
My problem is that the close on the server side is not called even if the
call should be executed. Because of that I have a lot of connections hanging
up into CLOSE_WAIT state.
For a better understanding of my problem I have replicate the communication
part between client and server into 2 small classes and run it on multiple
platforms.
I am writing to you guys because I was running with success the following
test program on Linux and Windows boxes but it fails on FreeBSD box (FreeBSD
www1.testing.com 6.2-RELEASE FreeBSD 6.2-RELEASE).

Client.java

*import java.io.*;
import java.net.*;
import java.nio.*;

class Client{
    private Socket socket;
    private ByteBuffer bb=ByteBuffer.wrap(new byte[]{7,8,9});
    private ByteBuffer rez=ByteBuffer.allocate(1024);

    public void connect(){
            int n=1;

            for(int i=0;i<n;i++){
                createSocket();
                try {
                    socket.getOutputStream().write(bb.array());
                    InputStream is=socket.getInputStream();
                    int count=0;
                    //byte b[]=new byte[1024];
                    rez.clear();
                    int total=0;
                    int b;
                    while((b=is.read())!=-1){
                        count++;
                        System.out.println("Client read:"+count);
                        rez.put((byte)b);
                        total+=count;
                    }
                    System.out.println("Client: Read a total of:"+total+
"count:"+count);
                    rez.flip();
                    for(int j:rez.array()){
                        System.out.println("RSj->"+j);
                    }
                } catch (IOException e) {
                    e.printStackTrace();

                }
                closeSocket();

            }
    }

    private void createSocket(){
        SocketAddress sa=new InetSocketAddress("127.0.0.1",9999);
        socket = new Socket();
        try {
            socket.connect(sa,1000);
            socket.setSoTimeout(1000);

        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Created Socket");
    }

   private void closeSocket(){
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Closed Socket");
    }

    public static void main(String args[]){
        new Client().connect();
    }

}

Server.java

import java.io.*;
import java.util.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;

class Server{
    private Selector selector;
    public void listen() throws IOException {
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        ServerSocket serverSocket =serverChannel.socket();
        selector= Selector.open();
        serverSocket.bind(new InetSocketAddress("localhost",9999));
        serverChannel.configureBlocking(false);
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);

        while(true){
            int n=selector.select(100);
            if(n==0){
                continue;
            }
            Iterator it=selector.selectedKeys().iterator();
            while(it.hasNext()){
                final SelectionKey key=(SelectionKey) it.next();
                System.out.println("Key:"+key.isReadable());

                if(key.isAcceptable()){
                    ServerSocketChannel ssc=(ServerSocketChannel)
key.channel();
                    SocketChannel sc=ssc.accept();
                    sc.configureBlocking(false);
                    Socket s=sc.socket();
                    sc.register(selector,SelectionKey.OP_READ);
                }
                if(key.isReadable()){
                    key.interestOps (key.interestOps() &
(~SelectionKey.OP_READ));

                    Runnable r=new Runnable(){
                        public void run() {
                            System.out.println("Run thread
"+key.toString());

                            try {
                                readChannel(key);
                            } catch (IOException e) {
                                System.out.println("CAnnot read from
channel");
                                e.printStackTrace();
                                try {
                                    key.channel().close();
                                } catch (IOException e1) {
                                    e1.printStackTrace();
                                }
                                key.selector().wakeup();
                            }

                        }
                        private void readChannel(SelectionKey key) throws
IOException {
                            SocketChannel sc=(SocketChannel) key.channel();
                            ByteBuffer bb=ByteBuffer.allocate(1024);
                            ByteBuffer rez=ByteBuffer.allocate(1024);
                            int count;
                            int total=0;
                            while((count=sc.read(bb))>0){
                                System.out.println("Read---"+count);
                                bb.flip();
                                rez.put(bb.array(),0,count);
                                bb.clear();
                                total+=count;
                            }
                            System.out.println("Server: Read total
of:"+total+" count "+count);
                            if(total>0){
                                rez.flip();
                                System.out.println("Here in printing on
server");
                                for(int i:rez.array()){
                                    if(i!=0)
                                        System.out.println("Ri->"+i);
                                }
                                byte a[]={3,4,5};
                                try{
                                    sc.write(ByteBuffer.wrap(a));
                                    System.out.println("After writing");
                                }catch(IOException e){
                                    System.out.println("CANNOT SEND BACK
response");
                                }
                            }

                            if(count<0){
                                sc.close();                  //<<<<<< NEVER
ENTER HERE <<<<
                                System.out.println("----------Closing
socket---------");
                                return;
                            }
                            System.out.println("Wake up selector");
                            int interest=key.interestOps() |
SelectionKey.OP_READ;
                            key.interestOps(interest);
                           System.out.println("End key:"+key.isReadable());
                            key.selector().wakeup();
                        }
                    };
                    new Thread(r).start();
                }else{
                     key.interestOps(key.interestOps()
&(~SelectionKey.OP_WRITE));
                    System.out.println("GET
HERE!!!!!-------"+key.isWritable()+"  "+key.isAcceptable()+"
"+key.isReadable());
                }
                it.remove();
            }
        }
    }

    public static void main(String args[]){
        try {
            new Server().listen();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


*Okay, it is a little bit longer but the main idea is as following.

1.The server is waiting for requests.
2.Client send some bytes and try to read response from
server                     ---->    3. Server selector activate for read and
read request into a separate thread
5.Client read response and after 1 second of inactivity get a read
timeout.    <-----     4. Server write some bytes to the client
6.Client close the
socket
----->     7.Server selector activate for read and read -1 from socket and
in this situation close the socket.

The problem appear on point 7. This point is never executed on FreeBSD and
is executed on all the other platform where I have tried.

My JVM is: *java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build diablo-1.5.0-b01)
Java HotSpot(TM) Server VM (build diablo-1.5.0_07-b01, mixed mode)*

I have also tried with linux-sun-jdk and the result is the same.
*java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b03)
Java HotSpot(TM) Server VM (build 1.5.0_07-b03, mixed mode)*

If anyone had some experience with this kind of problem please let me know
I would be very appreciated any help that I can get.

Thanks a lot and best regards
Calin


More information about the freebsd-java mailing list