Java NIO实现聊天功能
短信预约 -IT技能 免费直播动态提醒
本文实例为大家分享了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.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341