Java NIO实现聊天功能

本文实例为大家分享了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 selectionKeys = null;
 private Iterator iterator = null;
 private Iterator 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 clients = new ArrayList();
   //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 selectionKeys = null;
  Iterator 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 clientSessionList = new ArrayList();
 
 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实现聊天功能)