This program shows how to interrupt a socket channel.
/*
This program is a part of the companion code for Core Java 8th ed.
(http://horstmann.com/corejava)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/**
* This program shows how to interrupt a socket channel.
* @author Cay Horstmann
* @version 1.01 2007-06-25
*/
public class InterruptibleSocketTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new InterruptibleSocketFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class InterruptibleSocketFrame extends JFrame
{
public InterruptibleSocketFrame()
{
setSize(WIDTH, HEIGHT);
setTitle("InterruptibleSocketTest");
JPanel northPanel = new JPanel();
add(northPanel, BorderLayout.NORTH);
messages = new JTextArea();
add(new JScrollPane(messages));
interruptibleButton = new JButton("Interruptible");
blockingButton = new JButton("Blocking");
northPanel.add(interruptibleButton);
northPanel.add(blockingButton);
interruptibleButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
interruptibleButton.setEnabled(false);
blockingButton.setEnabled(false);
cancelButton.setEnabled(true);
connectThread = new Thread(new Runnable()
{
public void run()
{
try
{
connectInterruptibly();
}
catch (IOException e)
{
messages.append("\nInterruptibleSocketTest.connectInterruptibly: " + e);
}
}
});
connectThread.start();
}
});
blockingButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
interruptibleButton.setEnabled(false);
blockingButton.setEnabled(false);
cancelButton.setEnabled(true);
connectThread = new Thread(new Runnable()
{
public void run()
{
try
{
connectBlocking();
}
catch (IOException e)
{
messages.append("\nInterruptibleSocketTest.connectBlocking: " + e);
}
}
});
connectThread.start();
}
});
cancelButton = new JButton("Cancel");
cancelButton.setEnabled(false);
northPanel.add(cancelButton);
cancelButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
connectThread.interrupt();
cancelButton.setEnabled(false);
}
});
server = new TestServer();
new Thread(server).start();
}
/**
* Connects to the test server, using interruptible I/O
*/
public void connectInterruptibly() throws IOException
{
messages.append("Interruptible:\n");
SocketChannel channel = SocketChannel.open(new InetSocketAddress("localhost", 8189));
try
{
in = new Scanner(channel);
while (!Thread.currentThread().isInterrupted())
{
messages.append("Reading ");
if (in.hasNextLine())
{
String line = in.nextLine();
messages.append(line);
messages.append("\n");
}
}
}
finally
{
channel.close();
EventQueue.invokeLater(new Runnable()
{
public void run()
{
messages.append("Channel closed\n");
interruptibleButton.setEnabled(true);
blockingButton.setEnabled(true);
}
});
}
}
/**
* Connects to the test server, using blocking I/O
*/
public void connectBlocking() throws IOException
{
messages.append("Blocking:\n");
Socket sock = new Socket("localhost", 8189);
try
{
in = new Scanner(sock.getInputStream());
while (!Thread.currentThread().isInterrupted())
{
messages.append("Reading ");
if (in.hasNextLine())
{
String line = in.nextLine();
messages.append(line);
messages.append("\n");
}
}
}
finally
{
sock.close();
EventQueue.invokeLater(new Runnable()
{
public void run()
{
messages.append("Socket closed\n");
interruptibleButton.setEnabled(true);
blockingButton.setEnabled(true);
}
});
}
}
/**
* A multithreaded server that listens to port 8189 and sends numbers to the client, simulating a
* hanging server after 10 numbers.
*/
class TestServer implements Runnable
{
public void run()
{
try
{
ServerSocket s = new ServerSocket(8189);
while (true)
{
Socket incoming = s.accept();
Runnable r = new TestServerHandler(incoming);
Thread t = new Thread(r);
t.start();
}
}
catch (IOException e)
{
messages.append("\nTestServer.run: " + e);
}
}
}
/**
* This class handles the client input for one server socket connection.
*/
class TestServerHandler implements Runnable
{
/**
* Constructs a handler.
* @param i the incoming socket
*/
public TestServerHandler(Socket i)
{
incoming = i;
}
public void run()
{
try
{
OutputStream outStream = incoming.getOutputStream();
PrintWriter out = new PrintWriter(outStream, true /* autoFlush */);
while (counter < 100)
{
counter++;
if (counter <= 10) out.println(counter);
Thread.sleep(100);
}
incoming.close();
messages.append("Closing server\n");
}
catch (Exception e)
{
messages.append("\nTestServerHandler.run: " + e);
}
}
private Socket incoming;
private int counter;
}
private Scanner in;
private JButton interruptibleButton;
private JButton blockingButton;
private JButton cancelButton;
private JTextArea messages;
private TestServer server;
private Thread connectThread;
public static final int WIDTH = 300;
public static final int HEIGHT = 300;
}
Related examples in the same category