简单的AIO通讯模式

1 篇文章 0 订阅
本文对比了BIO、NIO和AIO的性能特点,强调AIO的异步非阻塞优势,避免了主线程的阻塞。通过实例展示了如何使用AsynchronousServerSocketChannel和AsynchronousSocketChannel实现AIO通讯,并通过CompletionHandler实现回调功能,以提高程序效率。
摘要由CSDN通过智能技术生成

相比于BIO(堵塞的IO,B是Blocking的意思),NIO(同步非堵塞IO)和AIO(异步非阻塞IO)的性能要比其高很多。异步通讯不以反复轮询为方式,主程序不会阻塞在死循环内,而是会继续的执行下去。如果收到消息,会自动调用回调函数,完成指定的操作。而NIO和AIO的复杂性显然大于BIO

前几天笔者写了一个NIO的通讯窗口,本次写一个AIO的窗口。主要用到
AsynchronousServerSocketChannel、AsynchronousSocketChannel。向server.accept方法中传递一个CompletionHandler,并实现completed和failed方法。complete方法是回调函数,当accept成功执行时会调用此方法。并且套件字也会传递给ComletionHandler.

运行出来就是这个效果:
进入界面
聊天窗口
代码如下:

package Message2;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

/*
 * @version:2.0
 * @author:阿基
 * @time:2020/8/22
 */
public class Message2 
{
	public static void main(String[] args)
	{
		EventQueue.invokeLater(()->{
			MessageFrame frame=new MessageFrame("Message 2.0");
			frame.setVisible(true);
		});
	}
}

class MessageFrame extends JFrame
{
	private JButton connectButton;
	private JButton sendButton;
	private JButton cancelButton;
	private JButton acceptButton;
	private JTextArea messages;
    String name;
	private JLabel hostLabel;
	private JLabel portLabel;
	private JTextField hostField;
	private JTextField portField;
	private JTextField messageField;
	private Server server;
	private SocketChannel socketChannel=null;
	public MessageFrame(String title)
	{
		super(title);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLayout(new BorderLayout());
		hostLabel=new JLabel("客户机IP地址:");
		hostField=new JTextField(10);
		portLabel=new JLabel("客户机端口");
		portField=new JTextField(5);
		JPanel northPanel=new JPanel();
		connectButton=new JButton("连接");
		WindowListener listener=new MyWindowHandler();
		addWindowListener(listener);
		connectButton.addActionListener(event->{
			String ip=hostField.getText().trim();
			int port =Integer.parseInt(portField.getText().trim());
			if(connect(ip,port))
				messages.append("连接成功\n");
		});
		northPanel.add(hostLabel,BorderLayout.NORTH);
		northPanel.add(hostField,BorderLayout.NORTH);
		northPanel.add(portLabel,BorderLayout.NORTH);
		northPanel.add(portField,BorderLayout.NORTH);
		northPanel.add(connectButton,BorderLayout.NORTH);
		add(northPanel,BorderLayout.NORTH);
		
		messages=new JTextArea("本机的IP地址查询DOS命令:ipconfig\n",20,60);
		add(new JScrollPane(messages),BorderLayout.CENTER);
		
		acceptButton=new JButton("开启服务器");
		sendButton=new JButton("发送信息");
		cancelButton=new JButton("退出");
		messageField=new JTextField(20);
			
		sendButton.addActionListener(event->{
		sendMessage();
		});
		
		acceptButton.addActionListener(event->{
			server=new Server();
			server.start();
		});
		
		cancelButton.addActionListener(event->
		{
			System.exit(1);
			
		});
		JPanel southPanel=new JPanel();
		southPanel.add(messageField,BorderLayout.CENTER);
		southPanel.add(acceptButton,BorderLayout.SOUTH);
		southPanel.add(sendButton,BorderLayout.SOUTH);
		southPanel.add(cancelButton,BorderLayout.SOUTH);
		
		add(southPanel,BorderLayout.SOUTH);
		pack();
		
	}
	//判断是否可以连接成功
	private boolean connect(String ip, int port) 
	{
		try {
			socketChannel=SocketChannel.open();
			return socketChannel.connect(new InetSocketAddress(ip,port));
		}catch(IOException e)
		{
			messages.append("连接失败:"+e);
			return false;
		}
	}

		
		public void sendMessage()
		{
			//输入IP和端口
			String ip=hostField.getText().trim();
			int port =Integer.parseInt(portField.getText().trim());
	       
			try {
				//创建通道,并建立连接
			socketChannel=SocketChannel.open();
			socketChannel.connect(new InetSocketAddress(ip,port));
			//设置为非阻塞模式
			socketChannel.configureBlocking(false);
			String word=messageField.getText();
			word=name+":"+word;
			if(word!=""|word!=null) {
				//建立缓存区
			ByteBuffer writeBuffer=ByteBuffer.allocate(1024*10);
			//将输入的字符串以“UTF-”转换为数组
			byte[] bytes=word.getBytes("UTF-8");
			//将数组写入缓存区
			writeBuffer.put(bytes);
			//翻转缓存区, The limit is set to 
			//the current position and then
			//the position is set to zero. If the mark is defined then it is discarded. 
			writeBuffer.flip();
			socketChannel.write(writeBuffer);
			messages.append(word+"\n");
			messageField.setText("");
			}
			}catch(IOException e)
			{
				messages.append("发送消息时出错:"+e);
			}
		}
		
	//创建服务器
	class Server extends Thread
	{
	
		@Override
		public void run()
		{
			try
			{
			AsynchronousServerSocketChannel server=AsynchronousServerSocketChannel.open();
			int port=Integer.parseInt(messageField.getText());
			server.bind(new InetSocketAddress(port));
			messages.append("服务器已开启,端口为"+port+"\n");
			messageField.setText("");
			server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
				

				@Override
				public void completed(AsynchronousSocketChannel channel, Void attachment)
				{
					server.accept(null,this);
					
					ByteBuffer  readBuffer=ByteBuffer.allocate(1024*10);
					channel.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {

						@Override
						public void completed(Integer result, ByteBuffer attachment) 
						{
							attachment.flip();	
							String word = null;
							try {
								word = new String(attachment.array(),"UTF-8");
							} catch (UnsupportedEncodingException e) {
								e.printStackTrace();
							}
							messages.append(word+"\n");
						}

						@Override
						public void failed(Throwable exc, ByteBuffer attachment) {
							messages.append("写入过程出现错误:"+exc+"\n");
							
						}
					});
				}

				@Override
				public void failed(Throwable exc, Void attachment) {
					// TODO Auto-generated method stub
					
				}
				
			});
			}catch(IOException e)
			{
				messages.append("服务器已经创建:"+e+"\n");
			}
		}
	}
	class MyWindowHandler extends WindowAdapter
	{
		public void  windowOpened(WindowEvent e)
		{
			name=JOptionPane.showInputDialog(null, "请输入昵称", "欢迎", JOptionPane.INFORMATION_MESSAGE);
			messages.append("你的昵称是:"+name+"\n");
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值