シンプルAIO通信モード

BIO(ブロックされたIO、Bはブロックを意味します)と比較して、NIO(同期非ブロックIO)およびAIO(非同期非ブロックIO)のパフォーマンスははるかに高くなります。非同期通信は繰り返しポーリングを使用せず、メインプログラムは無限ループでブロックされませんが、実行を継続します。メッセージを受信すると、コールバック関数が自動的に呼び出され、指定された操作が完了します。NIOとAIOの複雑さは、BIOの複雑さよりも明らかに大きいです。

著者は数日前にNIO通信ウィンドウを作成しましたが、今回はAIOウィンドウを作成しました。主に
AsynchronousServerSocketChannel、AsynchronousSocketChannelを使用しますCompletionHandlerをserver.acceptメソッドに渡し、完了したメソッドと失敗したメソッドを実装します。完全なメソッドはコールバック関数です。このメソッドは、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");
		}
	}
}

おすすめ

転載: blog.csdn.net/m0_47202518/article/details/108262037