`
dreamoftch
  • 浏览: 486382 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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 聊天室源码

    此项目基于java nio实现聊天室功能

    java nio聊天室源码

    用java nio写的一个完整的、可运行的聊天室程序;复制代码到项目后可直接运行。

    非GUI聊天室基于javaNIO

    服务端程序基于javaNIO,客户端程序基于旧IO,读完&lt;&lt;javaNIO&gt;&gt;后,导入eclipse即可运行,支持多人在线聊天,上下线通知.PS:非GUI程序,毕竟javaSwing用的少,不懂的地方大家可以一起讨论,评论必回!

    Java NIO 聊天室 JSwing

    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 { ...

    JAVA NIO 聊天室程序

    1.学习时的一个聊天室程序,将服务端改为NIO机制 2.支持多人同时在线局域网聊天 3.知识面:JSwing,NIO,消息包加密,解密,单列模式的线程安全机制等.

    Java NIO实战之聊天室功能详解

    主要介绍了Java NIO实战之聊天室功能,结合实例形式详细分析了java NIO聊天室具体的服务端、客户端相关实现方法与操作注意事项,需要的朋友可以参考下

    java基于NIO选择器Selector的多人聊天室

    本代码是基于JAVA技术NIO流的选择器Selector的多人聊天室,实现了多个客户端之间的聊天,拥有java窗体、画板等。

    Java NIO实战开发多人聊天室

    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 ...

    java NIO socket聊天室

    使用NIO socket不需要多线程来处理多个连接的请求,效率非常高 ...4,修改封装http做成短连接处理,就是一个小型的webserver,或者结合java2D和robot做远程监控 5,封装自己的协议可以做成自己需要的服务器端程序,

    java NIO socket聊天

    java NIO 高性能 socket通讯,服务端采用单线程,降低了cpu的压力,普通io socket通讯,server需要每个连接运行个线程,容易出现问题,效率也低

    基于java NIO的简单聊天软件示例

    JAVA NIO有两种解释:一种叫非阻塞IO(Non-blocking I/O),另一种也叫新的IO(New I/O),其实是同一个概念。它是一种同步非阻塞的I/O模型,也是...本例是使用java nio实现的简单聊天系统,界面简单,旨在学习java nio

    基于nio的简易聊天室

    基于nio 简易聊天室的服务端 客户端,有界面

    java NIO参考文档

    举个例子吧 你服务器做一个聊天室 按照以前的阻塞式IO 你必须为每个连接创建一个线程 因为当你调用如 in read buf 时 线程会阻塞在这里 而采用nio 只要注册了事件 它内部采用反应模式 当有IO事件发生时 再调度它 而...

    基于NIO非阻塞的java聊天demo(支持单聊和群聊)

    一个简单的javaNIO非阻塞的聊天小demo,支持单聊和群聊

    java NIO 学习 聊天室程序 (3)

    NULL 博文链接:https://tmdpzc.iteye.com/blog/1737928

    JavaNIO教程高清

    JavaNIO能够让读者快速的学习JavaNIO相关知识,讲解详细

    Java视频教程 Java游戏服务器端开发 Netty NIO AIO Mina视频教程

    [第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+多线程实现聊天室.zip

    多线程精品资源--Java NIO+多线程实现聊天室

    基于NIO的聊天室

    最近对NIO感兴趣,所以写了一个聊天室。目前简单的测试了一下,问题还是有一些的,不过可以运行了。 目前对NIO有了一个大致的认识。但是还不够深入,随着不断深入,肯定会更新新的版本的。如果大家有建议和意见的话...

    基于NIO的Java聊天室2

    简单修改后的版本,与上一次的代码相比,这次加上了发送信息的校验,用户没有昵称和信息内容是不可以发送的。 对上一次代码中同时启动两个客户端CPU占100%的BUG做了修改。

Global site tag (gtag.js) - Google Analytics