FileDocCategorySizeDatePackage
ChannelClose.javaAPI DocExample4728Mon May 20 00:24:28 BST 2002com.ronsoft.books.nio.channels

ChannelClose.java

package com.ronsoft.books.nio.channels;

import java.nio.ByteBuffer;
import java.nio.channels.InterruptibleChannel;
import java.nio.channels.FileChannel;
import java.nio.channels.ByteChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.io.FileInputStream;
import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Test interrupt and async close semantics of InterruptibleChannel objects.
 * This is test code to demonstrate bugs in the 1.4.0 implementation.
 * Use of /dev/tty with FileChannel will probably not work in future releases.
 *
 * @author Ron Hitchens (ron@ronsoft.com)
 * $Id: ChannelClose.java,v 1.3 2002/05/20 07:24:29 ron Exp $
 */
public class ChannelClose
{
	// Include a port number command line arg to use sockets, otherwise
	// /dev/tty will be used.  If you use sockets, use telnet in another
	// window to connect to the port and type some input.
	public static void main (String [] argv)
		throws Exception
	{
		int port = 0;

		if (argv.length > 0) {
			port = Integer.parseInt (argv [0]);
		}

		Thread.currentThread().setName ("Main");

		System.out.println ("--- Testing Interrupt Thread ---");
		testInterrupt (newChannel (port));

		System.out.println ("");
		System.out.println ("--- Testing Async Channel Close ---");
		testAsyncClose (newChannel (port));
	}

	// Create a new channel: if port == 0, FileChannel on /dev/tty, else
	// a SocketChannel from the first accept on the given port number
	private static ByteChannel newChannel (int netPort)
		throws Exception
	{
		if (netPort == 0) {
			FileInputStream fis = new FileInputStream ("/dev/tty");
			return (fis.getChannel());
		} else {
			ServerSocketChannel ssc = ServerSocketChannel.open();
			ssc.socket().bind (new InetSocketAddress (netPort));

			System.out.print ("Waiting for connection on port "
				+ netPort + "...");
			System.out.flush();

			ByteChannel channel = ssc.accept();
			ssc.close();
			System.out.println ("Got it");

			return (channel);
		}
	}

	private static void testInterrupt (ByteChannel channel)
		throws Exception
	{
		Sleeper sleeper = new Sleeper (channel);

		sleeper.setName ("Sleeper");

		try {
			ByteBuffer buffer = ByteBuffer.allocate (100);

			println ("starting sleeper thread");
			sleeper.start();

			println ("waiting for sleeper thread to issue read...");
			Thread.sleep (1000);

			println ("interrupting sleeper");
			sleeper.interrupt();

			Thread.sleep (100);	// avoid race with sleeper
			println ("issuing read on interrupted channel...");
			channel.read (buffer);
			println ("read completed OK");
		} catch (Throwable e) {
			println ("Caught " + e);
		} finally {
			println ("closing channel");
			channel.close();

			println ("joining sleeper "
				+ "(you may need to type something)...");
			sleeper.join();
		}
	}

	private static void testAsyncClose (ByteChannel channel)
		throws Exception
	{
		Sleeper sleeper = new Sleeper (channel);

		sleeper.setName ("Sleeper");

		try {
			ByteBuffer buffer = ByteBuffer.allocate (100);

			println ("starting sleeper thread");
			sleeper.start();

			println ("waiting for sleeper thread to issue read...");
			Thread.sleep (1000);

			println ("closing channel");
			channel.close();

			println ("joining sleeper "
				+ "(you may need to type something)...");
			sleeper.join();
		} catch (Throwable e) {
			println ("Caught " + e);
		}
	}

	// print output with a timestamp and the thread name.
	private static void println (String s)
	{
		SimpleDateFormat df = new SimpleDateFormat (
                        "HH:mm:ss.SSS");
		String ds = df.format (new Date());

		System.out.println (ds + " ("
			+ Thread.currentThread().getName()
			+ "): " + s);
	}

	// --------------------------------------------------------

	private static class Sleeper extends Thread
	{
		private ByteChannel channel;

		public Sleeper (ByteChannel channel)
		{
			super();

			this.channel = channel;
		}

		public void run()
		{
			ByteBuffer buffer = ByteBuffer.allocate (100);

			try {
				println ("issuing read...");
				int n = this.channel.read (buffer);
				println ("read complete, "
					+ "bytes read=" + n);

				System.out.print (" Buffer: '");
				buffer.flip();

				while (buffer.hasRemaining()) {
					char c = (char) buffer.get();

					switch (c) {
					case '\n':
						System.out.print ("\\n");
						break;

					case '\r':
						System.out.print ("\\r");
						break;

					default:
						System.out.print (c);
						break;
					}
				}

				System.out.println ("'");
			} catch (Throwable e) {
				println ("caught " + e);
			} finally {
				println ("exiting, "
					+ "interrupted=" + isInterrupted());
			}
		}
	}
}