博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(三) 可中断套接字
阅读量:4048 次
发布时间:2019-05-25

本文共 6688 字,大约阅读时间需要 22 分钟。

当连接到一个套接字时,当前线程将会被阻塞知道建立连接或产生超时位置。同样地,当通过套接字读写数据时,当前线程也会被阻塞知道操作成功或产生超时为止。

在交互式的应用中,也许会考虑为用户提供一个功能,用以取消那些不会成功的连接。但是当线程因套接字长时间无法响应而发生阻塞时,无法通过调用interrupt来接触阻塞。
为了中断套接字操作,可以使用java.nio包提供的一个特性 SocketChannel 类。
例: 打开SocketChannel

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

通道(Channel)并没有与之相关联的流。实际上,它所拥有的read和write方法都是通过调用buffer对象来实现的。ReadableByteChannel接口和WritableByteChannel接口都继承了Channel。

如果不想处理缓存,可以使用Scanner类来读取信息,因为Scanner有一个带有ReadableByteChannel参数的构造器:
例:Scanner(ReadableByteChannel source)构造一个新的 Scanner,它生成的值是从指定信道扫描的。

Scanner in = new Scanner(channel);

 

通过调用静态方法Channels.newOutputStream(),可以从通道中获取输出流。

OutputStream outStream = Channels.newOutputStream(channel);

 

上述操作都是必须做的,假设线程正在执行打开、读取或写入操作,此时如果线程发生中断,那么这些操作将不会陷入阻塞,而是以抛出异常的方式结束。

例:分别通过SocketChannel和InputStream读取

SocketChannel:

messages.append("Blocking:\n");        SocketChannel channel = SocketChannel.open(                new InetSocketAddress("localhost", 8189));        try{            in = new Scanner(channel);            while(!Thread.currentThread().isInterrupted()){                if(in.hasNextLine()){                    String line = in.nextLine();                }            }        }finally{            channel.close();        }
 

InputStream:

Socket socket = new Socket("localhost", 8189);        try{            in = new Scanner(socket.getInputStream());            while(!Thread.currentThread().isInterrupted()){                if(in.hasNextLine()){                    String line = in.nextLine();                }            }        }finally{            socket.close();        }
 

 

DEMO

 

import java.awt.EventQueue;import javax.swing.JFrame;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);			}		});	}}

 

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;public class InterruptibleSocketFrame extends JFrame {		public static final int WIDTH = 300;	public static final int HEIGHT = 300;		private Scanner in;	private JButton interruptibleButton;	private JButton blockingButton;	private JButton cancelButton;	private JTextArea messages;	private TestServer server;	private Thread connectThread;		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(Exception e){							messages.append("\nInterruptibleSocketTest.connectInterruptible" + 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){							e.printStackTrace();							messages.append("\nInterruptibleSocketTest.connectInterruptible" + 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();	}		public void connectInterruptibly() throws IOException{		messages.append("Blocking:\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);				}			});		}	}		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");					interruptibleButton.setEnabled(true);					blockingButton.setEnabled(true);				}			});		}	}		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);			}		}	}		class TestServerHandler implements Runnable{				private Socket incoming;		private int counter;				public TestServerHandler(Socket i){			incoming = i;		}				public void run(){			try{				OutputStream outStream = incoming.getOutputStream();				PrintWriter out = new PrintWriter(outStream, true);				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);			}		}	}}
 

 

转载地址:http://tayci.baihongyu.com/

你可能感兴趣的文章
Selenium-Switch与SelectApi接口详解
查看>>
Selenium-Css Selector使用方法
查看>>
Linux常用统计命令之wc
查看>>
测试必会之 Linux 三剑客之 sed
查看>>
Socket请求XML客户端程序
查看>>
Java中数字转大写货币(支持到千亿)
查看>>
Java.nio
查看>>
函数模版类模版和偏特化泛化的总结
查看>>
VMware Workstation Pro虚拟机不可用解决方法
查看>>
最简单的使用redis自带程序实现c程序远程访问redis服务
查看>>
redis学习总结-- 内部数据 字符串 链表 字典 跳跃表
查看>>
iOS 对象序列化与反序列化
查看>>
iOS 序列化与反序列化(runtime) 01
查看>>
iOS AFN 3.0版本前后区别 01
查看>>
iOS ASI和AFN有什么区别
查看>>
iOS QQ侧滑菜单(高仿)
查看>>
iOS 扫一扫功能开发
查看>>
iOS app之间的跳转以及传参数
查看>>
iOS __block和__weak的区别
查看>>
Android(三)数据存储之XML解析技术
查看>>