Java NIO实现聊天功能
作者:TCH987551623 发布时间:2022-06-12 08:31:31
标签: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.
来源:https://blog.csdn.net/TCH987551623/article/details/84611450


猜你喜欢
- Kotlin this详解及实例为了表示当前函数的接收者(receiver), 们使用this表达式:在类的成员函数中,this指向这个类的
- 现在再回过头理解,结合自己的体会, 选用最佳的方式描述这些算法,以方便理解它们的工作原理和程序设计技巧。本文适合做java面试准备的材料阅读
- .NET 4.5 中包含取消架构,允许以标准方式取消长时间运行的任务。每个阻塞调用都应支持这种机制。但目前,并不是所有阻塞调用都实现了这个新
- 本文实例讲述了C#使用Object类实现栈的方法。分享给大家供大家参考,具体如下:Stack类的代码:using System;using
- 金山公司面试题:一个字符串中可能包含a~z中的多个字符,如有重复,如String data="aavzcadfdsfsdhshgW
- JPA自定义VO类型转换(EntityUtils工具类)在JPA查询中,如果需要返回自定义的类,可以使用EntityUtils工具类,该类源
- 目录:DioManager:Dio辅助类NWMethod:请求方法,get、post等NWApi:大家都知道EntityFactory:js
- 问题情况:在使用 @TableId(type = IdType.AUTO)之后添加的id数字特别大原因:因为在第一次使用的时候没有加注解 所
- 在Android开发中很多时候会遇到一屏显示不下所有内容的现象,那大家也知道这个时候肯定会想到用scrollview来进行滚屏显示。这个时候
- 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号
- 本文实例讲述了C#实现将Email地址转成图片显示的方法。分享给大家供大家参考。具体实现方法如下:private final static
- 本文实例为大家分享了Java网络编程TCP程序设计的具体代码,供大家参考,具体内容如下[1] TCP编程的主要步骤客户端(client):1
- 在spring运行时,动态的添加bean,dapeng框架在解析xml的字段时,使用到了动态注册,注册了一个实现了FactoryBean类!
- 一. * 搭建及配置1 . * 简介 * 是架设在局域网的一种特殊的远程仓库,目的是代理远程仓库及部署第三方构件。有了 * 之后,当 Maven
- 引入字体首先在项目中创建fonts目录,然后将将ttf文件放到该目录下,然后在pubspec文件中添加该字体文件,如:...flutter:
- 登录添加验证码是一个非常常见的需求,网上也有非常成熟的解决方案,其实,要是自己自定义登录实现这个并不难,但是如果需要在 Spring Sec
- Toast一般用来显示一行文字,用法比较固定:Toast.makeText(Context context,String message,i
- 这是我的第一篇文章,我的想法是把自己再学习的
- 命令仓库 Ctrl + Shift + A 可以搜集对应命令快捷键1、基础快捷键1.1、无处不在的跳转项目之间的跳转1.1.1、项目项目之间
- 开发一款性能优良的应用是每一个Android开发者都必须经历的挑战。在移动端资源有限的前提下,提高应用的性能显得尤为重要。常见的提高APP性