Java NIO聊天功能
TCH987551623 人气:0server 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.
加载全部内容