java网络编程(二)可中断套接字

参考资料:java核心技术 卷II

为中断套接字操作,可使用java.nio包提供的SocketChannel类。可以使用如下方式打开SocketChannel:

SocketChannel channel = SocketChannel.open(new InetSocketAddress(host, port));

java实现如下:

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{
    //private static final long serialVersionUID = 1L;
    public InterruptibleSocketFrame(){
        setSize(WIDTH,HEIGHT);//设置窗体大小
        setTitle("InterruptibleSocketTest");

        JPanel northpJPanel =new JPanel();
        add(northpJPanel,BorderLayout.NORTH);//对容器进行定位

        messages=new JTextArea(); //JTextArea类,是一个显示纯文本的多行区域
        add(new JScrollPane(messages)); //JScrollPane类,为数据源提供一个窗口
        interruptilButton=new JButton("Interruptilbel");//JButton类,按钮
        blockingButton=new JButton("Blocking");

        northpJPanel.add(interruptilButton);//将button添加到窗口中
        northpJPanel.add(blockingButton);
        
        interruptilButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event){
                interruptilButton.setEnabled(false);
                blockingButton.setEnabled(false);//blocking按钮变成不可用
                cancelButton.setEnabled(true); //cancelButton按钮变成可用
                connectThread=new Thread(new Runnable(){//创建新线程
                    public void run() {
                        try{
                            connectInterruptibly();
                        } catch (Exception e) {
                            messages.append("\nInterruptibleSocketTest.connectInterruptibly: "+e);
                        }
                    }
                });
                connectThread.start();
            }
        });
        blockingButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                interruptilButton.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);
        northpJPanel.add(cancelButton);
        cancelButton.addActionListener(new ActionListener() {//点击cancel按钮来中断线程
            public void actionPerformed(ActionEvent e) {
                connectThread.interrupt();
                cancelButton.setEnabled(false);
                
            }
        });
        server =new TestServer(); //自定义的TestServer类
        new Thread(server).start();
        
    }
    /**
     * 连接到测试服务器,使用可中断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");
                    interruptilButton.setEnabled(true);
                    blockingButton.setEnabled(true);
                }
            });
        }
    }
    /**
     * 连接到测试服务器,使用阻塞I/O
     */
    public void connectBlocking() throws IOException{
        messages.append("Blocking:\n");
        Socket socket=new Socket("localhost",8189); //不可中断套接字
        try {
            in=new Scanner(socket.getInputStream());
            while (!Thread.currentThread().isInterrupted()){
                messages.append("Reading ");
                if(in.hasNextLine()){
                    String line=in.nextLine();
                    messages.append(line);
                    messages.append("\n");
                }
            }
        }finally{
            socket.close();
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    messages.append("Socket closed\n");
                    interruptilButton.setEnabled(true);
                    blockingButton.setEnabled(true);
                }
            });
        }
    }
    /**
     * 一个监听8189端口的多线程服务器,并向客户端连续发送数字,并在发送10个数字之后挂起
     */
    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 (Exception e) {
                messages.append("\nTestServer.run: "+e);
            }
        }

    }
    /**
     * 处理客户端用于服务器套接字链接的客户端输入
     */
    class TestServerHandler implements Runnable{
        public TestServerHandler(Socket i){
            incoming=i;
        }
        public void run() {
            try {
                OutputStream outputStream=incoming.getOutputStream();
                PrintWriter out=new PrintWriter(outputStream,true /*autoFulsh*/);
                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 JTextArea messages; 
    private JButton interruptilButton,blockingButton,cancelButton;
    private Thread connectThread;
    private TestServer server;

    public static final int WIDTH=550;
    public static final int HEIGHT=400;
}

执行程序,点击Blocking,在第一批的10个数字执行过程中,点击cancel,仍会继续输完10个数字,Interruptible和Blocking两个按钮变不可用。点击Interruptible可中断线程。

posted @ 2017-11-27 22:41  zeroingToOne  阅读(655)  评论(0编辑  收藏  举报