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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java基于NIO实现群聊系统

    本文实例为大家分享了Java基于NIO实现群聊系统的具体代码,供大家参考,具体内容如下 实例要求: 1.编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2.实现多人群聊 3.服务器端:可以监测用户上线,离线,并实现消息转发功能 4.客户端:通过 Channel 可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息(有服务器转发得到) 5.目的:进一步理解 NIO 非阻塞网络编程机制 6.示意图分析和代码 // 服务端: package com.atgui

  • java基于NIO实现群聊模式

    本文实例为大家分享了java基于NIO实现群聊模式的具体代码,供大家参考,具体内容如下 Client package com.qst.chat; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.

  • java NIO实现简单聊天程序

    本文实例为大家分享了java NIO实现简单聊天程序的具体代码,供大家参考,具体内容如下 服务端 功能: 1.接受客户端连接 2.发送消息 3.读取客户端消息 Server.java public class Server { private Selector selector; private ByteBuffer writeBuffer = ByteBuffer.allocate(1024); private ByteBuffer readBuffer = ByteBuffer.alloca

  • Java基于NIO实现聊天室功能

    本文实例为大家分享了Java基于NIO实现聊天室功能的具体代码,供大家参考,具体内容如下 Sever端 package com.qst.one; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.Channel; import java.nio.channels.SelectableChannel; impor

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

    本文实例讲述了Java NIO实战之聊天室功能.分享给大家供大家参考,具体如下: 在工作之余花了两个星期看完了<Java NIO>,总体来说这本书把NIO写的很详细,没有过多的废话,讲的都是重点,只是翻译的中文版看的确实吃力,英文水平太低也没办法,总算也坚持看完了.<Java NIO>这本书的重点在于第四章讲解的"选择器",要理解透还是要反复琢磨推敲:愚钝的我花了大概3天的时间才将NIO的选择器机制理解透并能较熟练的运用,于是便写了这个聊天室程序. 下面直接上代

  • Java NIO实现群聊系统

    本文实例为大家分享了Java NIO实现群聊系统的具体代码,供大家参考,具体内容如下 前面的文章介绍了NIO的三大核心组件并编写了BIO的一个demo实例,本文使用NIO写一个小应用实例,巩固并加深对NIO的理解. 实例要求: 1)编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2)实现多人群聊 3)服务器端:可以监测用户上线,离线,并实现消息转发功能 4)客户端:通过channel 可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息(有服务器转发得到

  • Java实现NIO聊天室的示例代码(群聊+私聊)

    功能介绍 功能:群聊+私发+上线提醒+下线提醒+查询在线用户 文件 Utils 需要用maven导入下面两个包 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <dependency> <group

  • Java基于NIO实现群聊功能

    本文实例为大家分享了Java基于NIO实现群聊功能的具体代码,供大家参考,具体内容如下 一.群聊服务器 package com.dashu.netty.group_chat; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.StandardCharsets; import java.util.Iterator; pu

  • java基于netty NIO的简单聊天室的实现

    一.为何要使用netty开发 由于之前已经用Java中的socket写过一版简单的聊天室,这里就不再对聊天室的具体架构进行细致的介绍了,主要关注于使用netty框架重构后带来的改变.对聊天室不了解的同学可以先看下我的博客(<JAVA简单聊天室的实现>) 本篇博客所使用的netty版本为4.1.36,完整工程已上传到Github(https://github.com/Alexlingl/Chatroom),其中lib文件夹下有相应的netty jar包和source包,自行导入即可. 1.为何要

  • Java NIO实现聊天室功能

    本文实例为大家分享了Java NIO实现聊天室功能的具体代码,供大家参考,具体内容如下 代码里面已经包含了必要的注释,这里不详述了.实现了基本的聊天室功能. 常量类: public class Constant { public static final int serverPort = 44444; } 服务端: package server; import java.io.IOException; import java.net.InetSocketAddress; import java.

随机推荐