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实现聊天室功能
用java nio写的一个完整的、可运行的聊天室程序;复制代码到项目后可直接运行。
服务端程序基于javaNIO,客户端程序基于旧IO,读完<<javaNIO>>后,导入eclipse即可运行,支持多人在线聊天,上下线通知.PS:非GUI程序,毕竟javaSwing用的少,不懂的地方大家可以一起讨论,评论必回!
import java.nio.channels.SocketChannel; import java.util.Iterator; import com.nio.user.ClientUser; import com.nio.user.ClientUserManager; import com.nio.user.UserData; public class NIOClient { ...
1.学习时的一个聊天室程序,将服务端改为NIO机制 2.支持多人同时在线局域网聊天 3.知识面:JSwing,NIO,消息包加密,解密,单列模式的线程安全机制等.
主要介绍了Java NIO实战之聊天室功能,结合实例形式详细分析了java NIO聊天室具体的服务端、客户端相关实现方法与操作注意事项,需要的朋友可以参考下
本代码是基于JAVA技术NIO流的选择器Selector的多人聊天室,实现了多个客户端之间的聊天,拥有java窗体、画板等。
01-Java NIO-课程简介.mp4 05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 08-Java NIO-Channel-ServerSocketChannel.mp4 09-Java NIO-Channel-SocketChannel.mp4 ...
使用NIO socket不需要多线程来处理多个连接的请求,效率非常高 ...4,修改封装http做成短连接处理,就是一个小型的webserver,或者结合java2D和robot做远程监控 5,封装自己的协议可以做成自己需要的服务器端程序,
java NIO 高性能 socket通讯,服务端采用单线程,降低了cpu的压力,普通io socket通讯,server需要每个连接运行个线程,容易出现问题,效率也低
JAVA NIO有两种解释:一种叫非阻塞IO(Non-blocking I/O),另一种也叫新的IO(New I/O),其实是同一个概念。它是一种同步非阻塞的I/O模型,也是...本例是使用java nio实现的简单聊天系统,界面简单,旨在学习java nio
基于nio 简易聊天室的服务端 客户端,有界面
举个例子吧 你服务器做一个聊天室 按照以前的阻塞式IO 你必须为每个连接创建一个线程 因为当你调用如 in read buf 时 线程会阻塞在这里 而采用nio 只要注册了事件 它内部采用反应模式 当有IO事件发生时 再调度它 而...
一个简单的javaNIO非阻塞的聊天小demo,支持单聊和群聊
NULL 博文链接:https://tmdpzc.iteye.com/blog/1737928
JavaNIO能够让读者快速的学习JavaNIO相关知识,讲解详细
[第4节] JavaNIO流-通道1.flv [第5节] Java NIO流-通道2.flv [第6节] Java NIO流-socket通道操作.flv [第7节] Java NIO流-文件通道操作.flv [第8节] Java NIO流-选择器 .flv [第9节] Java NIO流-选择器操作.flv...
多线程精品资源--Java NIO+多线程实现聊天室
最近对NIO感兴趣,所以写了一个聊天室。目前简单的测试了一下,问题还是有一些的,不过可以运行了。 目前对NIO有了一个大致的认识。但是还不够深入,随着不断深入,肯定会更新新的版本的。如果大家有建议和意见的话...
简单修改后的版本,与上一次的代码相比,这次加上了发送信息的校验,用户没有昵称和信息内容是不可以发送的。 对上一次代码中同时启动两个客户端CPU占100%的BUG做了修改。