Hi experts,

I am using nio package to transfer files from client to server. I use jdk1.4.2 on the client side (because have not upgraded our client code to new jre releases) and jdk1.5 on server side (because we use tomcat as webserver and latest tomcat is much stable and scalable but needs jre1.5). I use SocketChannel along with FileChannel to transfer the content of file to the server.

Client code snippet:
long bytesRead = fileChannel.transferTo(bytesTransferred, bufferSize, socketChannel);

Server code snippet:
long readBytes = fileChannel.transferFrom(socketChannel, 0, m_fileSize);

My problem is that all goes well unless the client machine crashes or the internet goes down, resulting in socketChannel on the client side not getting closed gracefully and hence no exception is thrown on the server sode! So, the thread on the server side that is trying to read from the socketChannel never dies (unless ofcourse webserver is restarted). I am sure I am missing something here, not sure what?

Please look at the following code and let me know what is wrong here! I appreciate you help and thank you for your time.

Regards,
Deepali

PS: I have tried to set timeout on socket and that didn't solve my problem and this is my first post so please be gentle, I know it is a big post and my problem could be silly!

Client code:
---------------

Code:
  
public class SimpleUploader
{
    public SimpleUploader()
    {
    }

    public void clientTransfer(String ip, int port, String fileName)
    {
        Socket socket = null;
        OutputStream outputStream = null;
        FileInputStream fileInputStream = null;
        FileChannel fileChannel = null;

        try
        {
            InetSocketAddress inetSockAddress = new InetSocketAddress(
                    InetAddress.getByName(ip), port);
            SocketChannel socketChannel = null;
            socketChannel = SocketChannel.open();
            socketChannel.connect(inetSockAddress);
            socket = socketChannel.socket();
            File inputFile = new File(fileName);
            fileInputStream = new FileInputStream(inputFile);

            // start pumping in the data
            fileChannel = fileInputStream.getChannel();
            boolean stillTransferring = true;
            long bytesTransferred = 0;
            long totalBytes = inputFile.length();

            while(bytesTransferred < totalBytes)
            {
                long bufferSize = 65536;

                if(totalBytes - bytesTransferred < bufferSize)
                {
                    bufferSize = (int) (totalBytes - bytesTransferred);

                    if(bufferSize <= 0)
                    {
                        bufferSize = (int) totalBytes;
                    }
                }

                long bytesRead = fileChannel.transferTo(bytesTransferred,
                        bufferSize,
                        socketChannel);

                if (bytesRead > 0)
                {
                    bytesTransferred += bytesRead;
                }
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if(socket != null)
            {
                try
                {
                    socket.close();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.out.println("Unable to close socket");
                }
            }

            if(outputStream != null)
            {
                try
                {
                    outputStream.close();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.out.println("Unable to close outputStream");
                }
            }

            if(fileChannel != null)
            {
                try
                {
                    fileChannel.close();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.out.println("Unable to close fileChannel");
                }
            }
        }
    }
}
Server code:
----------------

Code:
  
public class SimpleServer
    implements Runnable {
    protected boolean m_shouldStop = false;
    protected volatile Thread m_thread;
    protected String m_fileName = null;
    protected long m_fileSize = 0;

    private Socket m_socket = null;

    public SimpleServer(Socket socket, String fileName, long fileSize) {
        m_socket = socket;
        m_fileName = fileName;
        m_fileSize = fileSize;
    }

    public void start() {
        m_thread = new Thread(this);
        m_thread.start();
    }

    public void suspend() {
        m_shouldStop = true;
    }

    public void resume() {
    }

    public void stop() {
        m_shouldStop = true;
    }

    public boolean shouldStop() {
        return m_shouldStop;
    }

    public boolean isActive() {
        return (Thread.currentThread() == m_thread);
    }

    public void run() {
        RandomAccessFile fileOutputStream = null;

        try {
            if (fileOutputStream == null) {
                fileOutputStream = new RandomAccessFile(m_fileName, "rw");
                fileOutputStream.setLength(m_fileSize);
            }

            FileChannel fileChannel = fileOutputStream.getChannel();
            SocketChannel socketChannel = m_socket.getChannel();

            long readBytes = 0;
            readBytes = fileChannel.transferFrom(socketChannel, 0, m_fileSize);
            fileOutputStream.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally
        {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                    fileOutputStream = null;
                }
                catch (Exception e1) {
                    System.out.println("Failed to close file in exception: " +
                                       m_fileName);
                }
            }

            stop();
        }
    }
}