java NIO 聊天

 

server code : 

 

package com.tch.test.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class NioServer {

	private SocketChannel socketChannel = null;
	private Set<SelectionKey> selectionKeys = null;
	private Iterator<SelectionKey> iterator = null;
	private Iterator<SocketChannel> iterator2 = null;
	private SelectionKey selectionKey = null;
	
	public static void main(String[] args) {
		new NioServer().start();
	}
	
	private void start(){
		try {
			//create serverSocketChannel
			ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
			//bind the serverSocketChannel to a port
			serverSocketChannel.bind(new InetSocketAddress(7878));
			//when using selector ,should config the blocking mode of serverSocketChannel to non-blocking
			serverSocketChannel.configureBlocking(false);
			//create a selector to manage all the channels
			Selector selector = Selector.open();
			//reigst the serverSocketChannel to the selector(interest in accept event)
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
			//create a list to store all the SocketChannels
			List<SocketChannel> clients = new ArrayList<SocketChannel>();
			//create a ByteBuffer to store data
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			while(true){
				//this method will block until at least one of the interested events is ready 
				int ready = selector.select();
				if(ready > 0){//means at least one of the interested events is ready 
					selectionKeys = selector.selectedKeys();
					iterator = selectionKeys.iterator();
					while(iterator.hasNext()){
                        //the selectionKey contains the channel and the event which the channel is interested in 
                        selectionKey = iterator.next();
                        //accept event , means new client reaches
                        if(selectionKey.isAcceptable()){
                            //handle new client
                            ServerSocketChannel serverSocketChannel2 = (ServerSocketChannel)selectionKey.channel();
                            socketChannel = serverSocketChannel2.accept();
                            //when using selector , should config the blocking mode of socketChannel to non-blocking
                            socketChannel.configureBlocking(false);
                            //regist the socketChannel to the selector
                            socketChannel.register(selector, SelectionKey.OP_READ);
                            //add to client list
                            clients.add(socketChannel);
                        }else if(selectionKey.isReadable()){
                            //read message from client
                            socketChannel = (SocketChannel)selectionKey.channel();
                            buffer.clear();
                            try {
                                socketChannel.read(buffer);
                                buffer.flip();
                                //send message to every client
                                iterator2 = clients.iterator();
                                SocketChannel socketChannel2 = null;
                                while(iterator2.hasNext()){
                                    socketChannel2 = iterator2.next();
                                    while(buffer.hasRemaining()){
                                        socketChannel2.write(buffer);
                                    }
                                    //rewind method makes the buffer ready to the next read operation
                                    buffer.rewind();
                                }
                            } catch (IOException e) {
                                // IOException occured on the channel, remove from channel list
                                e.printStackTrace();
                                // Note: close the channel
                                socketChannel.close();
                                iterator2 = clients.iterator();
                                while(iterator2.hasNext()){
                                    if(socketChannel == iterator2.next()){
                                        // remove the channel
                                        iterator2.remove();
                                        System.out.println("remove the closed channel from client list ...");
                                        break;
                                    }
                                }
                            }
                        }
                        //important , remember to remove the channel after all the operations. so that the next selector.select() will 
                        //return this channel again .
						iterator.remove();
					}
				}
			}
		} catch (ClosedChannelException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

 

 

 

 client code :

 

package com.tch.nio.test;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class NioClient extends JFrame{

	private static final long serialVersionUID = 1L;
	private JTextArea area = new JTextArea("content :");
	private JTextField textField = new JTextField("textfield:");
	private JButton button = new JButton("send");
	private SocketChannel socketChannel = null;
	private ByteBuffer buffer = ByteBuffer.allocate(1024);
	private ByteBuffer buffer2 = ByteBuffer.allocate(1024);
	private String message = null;

	public static void main(String[] args) throws Exception {
		NioClient client = new NioClient();
		client.start();
	}
	
	private void start() throws IOException{
		setBounds(200, 200, 300, 400);
		setLayout(new GridLayout(3, 1));
		add(area);
		add(textField);
		//create a socketChannel and connect to the specified address
		socketChannel = SocketChannel.open(new InetSocketAddress("localhost", 7878));
		//when using selector , should config the blocking mode of socketChannel to non-blocking
		socketChannel.configureBlocking(false);
		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				try {
					message = textField.getText();
					textField.setText("");
					//send message to server
					buffer.put(message.getBytes("utf-8"));
					buffer.flip();
					while(buffer.hasRemaining()){
						socketChannel.write(buffer);
					}
					buffer.clear();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		add(button);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		Set<SelectionKey> selectionKeys = null;
		Iterator<SelectionKey> iterator = null;
		SelectionKey selectionKey = null;
		Selector selector = Selector.open();
		//reigst the socketChannel to the selector(interest in read event)
		socketChannel.register(selector, SelectionKey.OP_READ);
		while(true){
			//this method will block until at least one of the interested events is ready 
			int ready = selector.select();
			if(ready > 0){//means at least one of the interested events is ready 
				selectionKeys = selector.selectedKeys();
				iterator = selectionKeys.iterator();
				while(iterator.hasNext()){
					selectionKey = iterator.next();
					//read message from server ,then append the message to textarea
					if(selectionKey.isReadable()){
						socketChannel.read(buffer2);
						buffer2.flip();
						area.setText(area.getText().trim()+"\n"+new String(buffer2.array(),0,buffer2.limit(),"utf-8"));
						buffer2.clear();
					}
					//important , remember to remove the channel after all the operations. so that the next selector.select() will 
					//return this channel again .
					iterator.remove();
				}
			}
		}
	}
	
}

 

run server first , then is client , type message and send , ok

 

 

 

使用Mina实现聊天:

 

server:

 

package com.tch.test.jms.origin.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyServer {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(MyServer.class);
	private List<IoSession> clientSessionList = new ArrayList<IoSession>();
	
	public static void main(String[] args) {
	    
		IoAcceptor acceptor = new NioSocketAcceptor();

		acceptor.getFilterChain().addLast("logger", new LoggingFilter());
		acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));

		acceptor.setHandler(new MyServer().new MyServerIoHandler());
		
		try {
			acceptor.bind(new InetSocketAddress(10000));
		} catch (IOException ex) {
			LOGGER.error(ex.getMessage(), ex);
		}
	}
	
	class MyServerIoHandler extends IoHandlerAdapter{
        
        @Override
        public void sessionCreated(IoSession session) throws Exception {
            LOGGER.info("sessionCreated");
        }
        
        @Override
        public void sessionOpened(IoSession session) throws Exception {
            LOGGER.info("sessionOpened");
            if(! clientSessionList.contains(session)){
                clientSessionList.add(session);
            }
        }

        @Override
        public void sessionClosed(IoSession session) throws Exception {
            LOGGER.info("sessionClosed");
            clientSessionList.remove(session);
        }

        @Override
        public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
            LOGGER.info("sessionIdle");
        }

        @Override
        public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
            LOGGER.error(cause.getMessage(), cause);
            session.close(true);
            clientSessionList.remove(session);
        }

        @Override
        public void messageReceived(IoSession session, Object message) throws Exception {
            LOGGER.info("messageReceived:" + message);
            for(IoSession clientSession : clientSessionList){
                clientSession.write(message);
            }
        }

        @Override
        public void messageSent(IoSession session, Object message) throws Exception {
            LOGGER.info("messageSent:" + message);
        }
    }
}

 

 

client : 

 

package com.tch.test.jms.origin.client;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NioClient extends JFrame{
    private static final Logger LOGGER = LoggerFactory.getLogger(NioClient.class);
	private static final long serialVersionUID = 1L;
	private JTextArea area = new JTextArea("content :");
	private JTextField textField = new JTextField("textfield:");
	private JButton button = new JButton("send");
	private String message = null;
	private MyClientIoHandler handler;
	private IoSession session;

	public static void main(String[] args) throws Exception {
		NioClient client = new NioClient();
		client.start();
	}
	
	private void start() throws IOException{
		setBounds(200, 200, 300, 400);
		setLayout(new GridLayout(3, 1));
		add(area);
		add(textField);
		
		IoConnector connector = new NioSocketConnector();
        connector.setConnectTimeoutMillis(10 * 1000);
        
        connector.getFilterChain().addLast("logger", new LoggingFilter());
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
        
        handler = new MyClientIoHandler(this);
        connector.setHandler(handler);
		
		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
			    sendMessage();
			}
		});
		add(button);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		
		IoSession session = null;
        try {
            ConnectFuture future = connector.connect(new InetSocketAddress("localhost", 10000));
            future.awaitUninterruptibly();
            session = future.getSession();
        } catch (RuntimeIoException e) {
            LOGGER.error(e.getMessage(), e);
        }
        session.getCloseFuture().awaitUninterruptibly();
        connector.dispose();
	}
	
	private void sendMessage() {
        try {
            message = textField.getText();
            textField.setText("");
            if(session == null || ! session.isConnected()){
                throw new RuntimeException("session is null");
            }
            session.write(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
	
	class MyClientIoHandler extends IoHandlerAdapter{
	    private NioClient client;
        public MyClientIoHandler(NioClient client){
            this.client = client;
        }
        @Override
        public void sessionCreated(IoSession session) throws Exception {
            LOGGER.info("sessionCreated");
        }

        @Override
        public void sessionOpened(IoSession session) throws Exception {
            LOGGER.info("sessionOpened");
            client.session = session;
        }

        @Override
        public void sessionClosed(IoSession session) throws Exception {
            LOGGER.info("sessionClosed");
        }

        @Override
        public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
            LOGGER.info("sessionIdle");
        }

        @Override
        public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
            LOGGER.error(cause.getMessage(), cause);
            session.close(true);
        }

        @Override
        public void messageReceived(IoSession session, Object message) throws Exception {
            LOGGER.info("messageReceived: " + message);
            if (message.toString().equalsIgnoreCase("Bye")) {
                session.close(true);
            }
            area.setText(area.getText().trim()+"\n"+message);
        }

        @Override
        public void messageSent(IoSession session, Object message) throws Exception {
            LOGGER.info("messageSent: " + message);
        }
    }
	
}

 

 

OK.

 

你可能感兴趣的:(java,nio)