当连接到一个套接字时,当前线程将会被阻塞知道建立连接或产生超时位置。同样地,当通过套接字读写数据时,当前线程也会被阻塞知道操作成功或产生超时为止。
在交互式的应用中,也许会考虑为用户提供一个功能,用以取消那些不会成功的连接。但是当线程因套接字长时间无法响应而发生阻塞时,无法通过调用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);
}
}
}
}
分享到:
相关推荐
异步套接字是网络编程中的一个重要概念,它在服务器端和客户端的通信中起着关键作用。在本文中,我们将深入探讨异步套接字的工作原理、优势以及如何在服务器端和客户端实现异步通信。 首先,让我们理解什么是异步套...
流式套接字,也称为TCP(Transmission Control Protocol)套接字,是网络编程中常用的一种数据传输方式。TCP提供了一种面向连接、可靠的数据传输服务,确保了数据的顺序和完整性,适用于需要稳定、高效交换大量数据...
三、TCP套接字编程 1. 服务器端:首先创建套接字,然后绑定到特定端口,调用listen()开始监听。当有客户端连接时,accept()返回一个新套接字处理连接请求,服务器通过这个新套接字与客户端通信。 2. 客户端:创建套...
2. Socket error 10004 - 中断函数调用:该错误码表示套接字操作被中断。 3. Socket error 10013 - 权限拒绝:该错误码表示套接字操作没有足够的权限。 4. Socket error 10014 - 坏地址:该错误码表示套接字操作的...
- 异常情况下,如网络中断、内存不足,需确保正确关闭套接字,释放资源。 - 使用`closesocket()`(Windows)或`close()`(Unix-like)关闭套接字。 8. **性能优化** - 对于大量并发连接,优化I/O模型(如epoll的...
在计算机网络编程中,"套接字通信"是实现进程间通信(IPC)的重要机制,特别是在分布式系统和互联网应用中。套接字是操作系统提供的一个接口,允许应用程序通过它发送和接收数据。本文将深入探讨"套接字通信",特别...
在套接字编程中,异常处理是必不可少的。由于网络通信可能因各种原因中断,如网络故障、客户端断开连接等,因此需要捕获和处理IOException。 此外,关闭套接字和流是良好的编程习惯,可以避免资源泄露。通常,应当...
5. 异常处理:在MFC套接字编程中,应捕获CAsyncSocket类的异常,如CErrors、CInternetException等,以处理网络错误和中断。 6. 客户端(Client)与服务器端(Server)的角色:客户端发起连接请求,通常执行发送数据...
在IT行业中,套接字编程是网络通信的基础,特别是在C语言环境下,它为开发者提供了低级别的接口来构建网络应用程序。TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,广泛应用于互联网上...
流式套接字编程是网络通信中的基础概念,主要用于实现数据的双向连续传输。在.NET框架和C++编程中,我们可以利用系统提供的API或者库来创建流式套接字(Stream Socket)应用,如本例中的"server.exe"服务器端和...
在IT领域,套接字(Socket)是一种网络通信机制,它是应用程序通过网络与另一应用程序进行数据交换的一种方式。本文将详细解析"完整的套接字数据库客户端"这一主题,包括套接字的基本概念、数据库客户端的原理以及...
《易语言套接字源码例程》是一个针对易语言编程环境的套接字编程教程资源包。在本文中,我们将深入探讨易语言中的套接字编程基础,以及如何利用提供的源码例程进行学习和实践。 易语言,作为一款国内自主研发的中文...
8. **错误处理**:在开发同步套接字服务器时,需要考虑各种异常情况,如网络中断、超时、资源耗尽等,确保服务器的健壮性。 9. **数据编码与解码**:在传输过程中,数据通常需要进行编码(如JSON、XML或二进制格式...
本主题将深入探讨如何使用MFC结合套接字技术实现文件传输功能,特别是带用户界面的程序。 首先,我们需要理解套接字(Socket)。套接字是网络通信的基础,它提供了一种进程间通信的接口,使得运行在不同计算机上的...
7. **错误处理**:在套接字编程中,必须对可能出现的网络错误进行妥善处理,例如连接中断、数据传输错误等。这通常涉及检查返回值,使用`WSAGetLastError`获取错误代码,并根据情况采取相应的恢复策略。 8. **安全...
【套接字五元组】是指在计算机网络通信中,用来唯一标识一个网络连接的五个元素的组合。这五个元素包括:协议(Protocol)、本地地址(Local Address)、本地端口(Local Port)、远程地址(Remote Address)和远程...
【TCP网口套接字聊天程序】是一种基于TCP协议实现的网络通信应用,它允许两台计算机之间进行类似QQ的实时聊天。在这个程序中,一台计算机作为服务器,提供监听和接收连接的服务,另一台计算机作为客户端,发起连接...
【标题】:“聊天室代码 套接字 java” 【描述】:“java 聊天室代码 套接字很简单 适合于初级者” 在Java编程中,创建一个简单的聊天室涉及到网络通信的核心概念——套接字(Socket)。套接字是网络编程的基本...
**Winsock教程_套接字试验** Winsock是Windows操作系统中的网络编程接口,它提供了标准的Berkeley套接字API,使得程序员可以编写跨平台的网络应用程序。本教程旨在为初学者提供一个全面的Winsock学习框架,通过实践...
在IT领域,套接字编程是网络通信的基础,它允许应用程序通过网络发送和接收数据。本文将深入探讨如何使用C语言实现大文件的传输,主要涉及客户端与服务器之间的交互。 首先,我们需要理解套接字(Socket)的概念。...