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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
package com.ui.server; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ServerBootFrame extends JFrame { /** * */ private static final long serialVersionUID = 1L; JPanel jp = new JPanel(new BorderLayout()); JPanel jp1 = new JPanel(new FlowLayout()); JScrollPane jsp1 = new JScrollPane(); JButton jbStart = new JButton("启动"); JButton jbEnd = new JButton("关闭"); JTextArea jtaState = new JTextArea(10, 25); Font font = new Font("Serif", Font.BOLD, 18); Color fore = Color.YELLOW; Color back = new Color(81, 217, 251); public ServerBootFrame(String title) { super(title); this.getContentPane().add(jp); jp.add(jsp1, "Center"); jsp1.getViewport().add(jtaState); jp.add(jp1, "South"); jp1.add(jbStart); jp1.add(jbEnd); jtaState.setFont(font); jtaState.setForeground(fore); jtaState.setBackground(back); jp1.setBackground(back); this.setResizable(false); this.setLocation(250, 250); } public void showFrame() { this.pack(); this.setVisible(true); } public void bootingServer(final BootEndInterface bt) { this.jbStart.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { bt.boot(); } }); } public void endingServer(final BootEndInterface ed) { this.jbEnd.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ed.end(); } }); } public void closeWindow(final BootEndInterface ed) { this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e1) { ed.end(); } }); } public void appendStringTojtaState(String str) { jtaState.append(str); } } package com.ui.client; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.sql.*; public class LoginFrame extends JFrame { JLabel jUserName=new JLabel("用户姓名:"); JLabel jUserPsd=new JLabel("用户密码:"); JTextField txtUserName=new JTextField("",10); JPasswordField txtUserPsd=new JPasswordField(10); JButton okButton=new JButton("确定"); JButton regButton=new JButton("注册"); JPanel jp=new JPanel(new GridLayout(2,1)); JPanel jp1=new JPanel(new FlowLayout(FlowLayout.CENTER)); JPanel jp2=new JPanel(new FlowLayout(FlowLayout.LEFT)); JPanel jp3=new JPanel(new FlowLayout()); Font f=new Font("Serif",Font.BOLD,15); public LoginFrame() { super("用户登陆界面"); this.setLocation(250,250); this.getContentPane().add(jp,"Center"); this.getContentPane().add(jp3,"South"); jp.add(jp1);jp.add(jp2); jp1.add(jUserName);jp1.add(txtUserName); jp2.add(jUserPsd);jp2.add(txtUserPsd); jp3.add(okButton);jp3.add(regButton); txtUserName.setFont(f); txtUserPsd.setFont(f); txtUserPsd.setEchoChar('x'); txtUserName.setToolTipText("请输入用户名"); txtUserPsd.setToolTipText("请输入用户密码"); okButton.addActionListener(new SolveButtonEvent(1)); regButton.addActionListener(new SolveButtonEvent(2)); this.setResizable(false); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void showWindow() { this.pack(); this.setVisible(true); } public void closeWindow() { this.dispose(); } public String getUserName() { return this.txtUserName.getText().trim(); } public String getUserPassword() { return new String(this.txtUserPsd.getPassword()); } class SolveButtonEvent implements ActionListener { int select=0; public SolveButtonEvent(int select) { this.select=select; } public void actionPerformed(ActionEvent e) { //int x=(int) LoginFrame.this.txtUserName.getLocationOnScreen().getX(); //int y=(int) LoginFrame.this.txtUserName.getLocationOnScreen().getY(); String userName=LoginFrame.this.getUserName(); String userPsd=LoginFrame.this.getUserPassword(); int nameLength=userName.length(); int psdLength=userPsd.length(); if(select==1) { if(nameLength>0 && psdLength>0 ) { if(LoginFrame.this.query(userName,userPsd)==true) { LoginFrame.this.closeWindow(); //new Client(); } else { MyDialog md=new MyDialog(LoginFrame.this,"提示窗口","错误!","用户名或密码错误.\n登陆失败"); md.showDialog(); } } else { if(nameLength==0) { MyDialog md=new MyDialog(LoginFrame.this,"提示窗口","提示","用户名不能为空"); md.showDialog(); } else if(psdLength==0) { MyDialog md=new MyDialog(LoginFrame.this,"提示窗口","提示","用户密码不能为空"); md.showDialog(); } } } else if(select==2) { RegisterFrame rf=new RegisterFrame(LoginFrame.this); rf.showWindow(); } } } public boolean query(String userName,String userPsd) { Connection conn=null; PreparedStatement psm=null; ResultSet rs=null; String sql="select * from user_manager where name=? and psd=?"; boolean result=false; try { Class.forName("oracle.jdbc.driver.OracleDriver"); conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xdf","scott","tiger"); psm=conn.prepareStatement(sql); psm.setString(1,userName); psm.setString(2,userPsd); rs=psm.executeQuery(); //rs结果集指向第一条记录的前一个位置 //如果第一条记录为空表示用户名或密码错误 if(rs.next()==true) { result=true; this.closeWindow(); } psm.close(); conn.close(); } catch(ClassNotFoundException e1){ e1.printStackTrace(); } catch(SQLException e2){ e2.printStackTrace(); } catch(Exception e3){ e3.printStackTrace(); } return result; } } package com.nio.client; 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 com.nio.user.ClientUser; import com.nio.user.ClientUserManager; import com.nio.user.UserData; public class NIOClient { private ClientUserManager cltManager = null; //通道管理器 private Selector selector; /** * 获得一个Socket通道,并对该通道做一些初始化的工作 * @param ip 连接的服务器的ip * @param port 连接的服务器的端口号 * @throws IOException */ public void initClient(String ip,int port) throws IOException { cltManager = ClientUserManager.instance(); // 获得一个Socket通道 SocketChannel channel = SocketChannel.open(); // 设置通道为非阻塞 channel.configureBlocking(false); // 获得一个通道管理器 this.selector = Selector.open(); // 客户端连接服务器,其实方法执行并没有实现连接,需要在listen()方法中调 //用channel.finishConnect();才能完成连接 channel.connect(new InetSocketAddress(ip,port)); //将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_CONNECT事件。 channel.register(selector, SelectionKey.OP_CONNECT); } /** * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理 * @throws IOException * @throws InterruptedException */ @SuppressWarnings("unchecked") public void listen() throws IOException, InterruptedException { // 轮询访问selector while (true) { // 选择一组可以进行I/O操作的事件,放在selector中,客户端的该方法不会阻塞, //这里和服务端的方法不一样,查看api注释可以知道,当至少一个通道被选中时, //selector的wakeup方法被调用,方法返回,而对于客户端来说,通道一直是被选中的 selector.select(); // 获得selector中选中的项的迭代器 Iterator ite = this.selector.selectedKeys().iterator(); while (ite.hasNext()) { SelectionKey key = (SelectionKey) ite.next(); // 连接事件发生 if (key.isConnectable()) { SocketChannel channel = (SocketChannel) key .channel(); System.out.println("channel client ?" + channel); // 如果正在连接,则完成连接 if(channel.isConnectionPending()){ channel.finishConnect(); } //设置成非阻塞 channel.configureBlocking(false); //在这里可以给服务端发送信息哦 //channel.write(ByteBuffer.wrap(new String("向服务端发送了一条信息").getBytes())); //在和服务端连接成功之后,为了可以接收到服务端的信息,需要给通道设置读的权限。 channel.register(this.selector, SelectionKey.OP_READ); //添加用户 UserData userData = new UserData(); userData.lineState = 1; userData.channel = channel; cltManager.addUser(userData); //连接成功发送一个通知消息 UIClient.sendUserInfoMsg(); } else if (key.isReadable()) { ClientUser cltUser = cltManager.getUser((SocketChannel)key.channel()); if (!cltUser.read()) { key.channel().close(); } } //删除已选的key,以防重复处理 ite.remove(); } } } } package com.nio.server; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.HashMap; import java.util.Iterator; import java.util.Vector; import com.nio.user.ServerUser; import com.nio.user.ServerUserManager; import com.nio.user.UserData; import com.ui.server.BootEndInterface; import com.ui.server.ServerBootFrame; public class NIOServer implements BootEndInterface { private ServerBootFrame serverFrame = new ServerBootFrame("服务器端"); private ServerUserManager userManager = null; HashMap<String, String> hmClient = new HashMap<String, String>(); Vector<String> client = new Vector<String>(); int count = 0; private static NIOServer nioServer = null; public NIOServer() { serverFrame.showFrame(); serverFrame.bootingServer(this); serverFrame.endingServer(this); serverFrame.closeWindow(this); nioServer = this; } // 通道管理器 private Selector selector; /** * 获得一个ServerSocket通道,并对该通道做一些初始化的工作 * * @param port * 绑定的端口号 * @throws IOException */ public void initServer(int port) throws IOException { serverFrame.appendStringTojtaState("服务器(NIO机制)启动中......\n"); // 获得一个ServerSocket通道 ServerSocketChannel serverChannel = ServerSocketChannel.open(); // 设置通道为非阻塞 serverChannel.configureBlocking(false); // 将该通道对应的ServerSocket绑定到port端口 serverChannel.socket().bind(new InetSocketAddress(port)); // 获得一个通道管理器 this.selector = Selector.open(); // 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后, // 当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。 serverChannel.register(selector, SelectionKey.OP_ACCEPT); //System.out.println("serverChannel 0?" + serverChannel); } /** * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理 * * @throws IOException */ @SuppressWarnings("unchecked") public void listen() throws IOException { // System.out.println("服务端启动成功!"); serverFrame.appendStringTojtaState("服务器(NIO机制)启动成功......\n"); // 轮询访问selector while (true) { // 当注册的事件到达时,方法返回;否则,该方法会一直阻塞 selector.select(); // 获得selector中选中的项的迭代器,选中的项为注册的事件 Iterator<?> ite = this.selector.selectedKeys().iterator(); while (ite.hasNext()) { SelectionKey key = (SelectionKey) ite.next(); // 客户端请求连接事件 if (key.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) key .channel(); // 获得和客户端连接的通道 SocketChannel channel = server.accept(); System.out.println("channel A?" + channel); // 设置成非阻塞 channel.configureBlocking(false); // 在这里可以给客户端发送信息哦 // channel.write(ByteBuffer.wrap(new // String("向客户端发送了一条信息").getBytes())); // 在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限。 channel.register(this.selector, SelectionKey.OP_READ); // 添加一个玩家对象 UserData userData = new UserData(); userData.lineState = 1; userData.channel = channel; userManager.addUser(userData); } else if (key.isReadable()) { ServerUser serverUser = userManager .getUser((SocketChannel) key.channel()); // 读取数据失败 if (!serverUser.read()) { serverUser.clean(); key.channel().close(); } } // 删除已选的key,以防重复处理 ite.remove(); } } } /** * 启动服务端测试 * * @throws IOException */ public static void main(String[] args) throws IOException { new NIOServer(); } @Override public void boot() { userManager = ServerUserManager.instance(); userManager.initUsers(); serverFrame.appendStringTojtaState("创建玩家内存数据对象成功...\n"); new Thread(new Runnable() { @Override public void run() { try { NIOServer.this.initServer(5555); NIOServer.this.listen(); } catch (Exception e) { serverFrame.appendStringTojtaState("服务器启动失败......\n"); } } }).start(); //服务端主逻辑处理 new Thread(new Runnable() { @Override public void run() { try { while (true) { Thread.sleep(1); userManager.run(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } @Override public void end() { if (selector != null) { try { selector.close(); selector = null; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.exit(0); } public void solveMsg(String message) { try { System.out.println(message); // 对消息进行分析 String msg[] = message.split("#"); if (msg[0].equals("AddUser") == true) { hmClient.put(msg[1], msg[2]); sendUsersToOneUser(msg[1]); if (likeThisName(msg[1]))// 如果出现同名用户,则在用户名后面添加数字来区分 { msg[1] = msg[1] + count; } client.add(msg[1]); serverFrame.appendStringTojtaState(msg[1] + "上线...\n"); sendMessageToAllUsers( "AddUser" + "#" + msg[1] + "#" + hmClient.get(msg[1]), msg[1]); } else if (msg[0].equals("UserQuit") == true) { sendMessageToAllUsers("UserQuit" + "#" + msg[1] + "#" + hmClient.get(msg[1]), msg[1]); serverFrame.appendStringTojtaState(msg[1] + "离线...\n"); deleteKeyValue(msg[1]); client.remove(msg[1]); // 应该删除vecUser容器中的对应的Socket对象 } else if (msg[0].equals("Message") == true) { // 如果将消息发送给特定用户 if (msg[1].equals("One") == true) { sendMessageToOneUser("Message" + "#" + msg[2] + "#" + msg[6], msg[4]); } else// 将消息发送给全部用户 { sendMessageToAllUsers("Message" + "#" + msg[2] + "#" + msg[4], msg[2]); } } } catch (Exception e) { e.printStackTrace(); } } public void sendMessageToAllUsers(String msg, String notSendToThisUserName) throws UnsupportedEncodingException { ServerUser lstUsers[] = userManager.getUsers(); for (int i = 0; i < lstUsers.length; i++) { if (lstUsers[i].channel != null) { String address = lockOut("" + lstUsers[i].channel.socket().getRemoteSocketAddress()); if ( !address.equals(hmClient.get(notSendToThisUserName)) ) { lstUsers[i].write(msg.getBytes("utf-8")); } } } } public void sendMessageToOneUser(String msg, String sendToThisUserName) throws UnsupportedEncodingException { ServerUser lstUsers[] = userManager.getUsers(); for (int i = 0; i < lstUsers.length; i++) { if (lstUsers[i].channel != null) { String address = lockOut("" + lstUsers[i].channel.socket().getRemoteSocketAddress()); if ( address.equals(hmClient.get(sendToThisUserName)) ) { lstUsers[i].write(msg.getBytes("utf-8")); break; } } } } // 方法完成将在线用户添给用户的下拉表中 public void sendUsersToOneUser(String newUserName) throws UnsupportedEncodingException { Iterator<String> it = client.listIterator(); for (; it.hasNext();) { String name = it.next(); String ipAndPort = hmClient.get(name); sendMessageToOneUser("OnlyAddUser" + "#" + name + "#" + ipAndPort, newUserName); } } // 将键值对添加到hmClient哈希表中 public void createKeyValue(String userName, String socketAddress) { hmClient.put(userName, socketAddress); } // 从哈希表中删除指定键值对(键为:userName); public void deleteKeyValue(String userName) { hmClient.remove(userName); } // 将字符串前面的斜杠去掉 public String lockOut(String socketAddress) { return socketAddress.substring(1, socketAddress.length()); } // 如果client容器中存放的用户名出现相似用户,则用户名后面添加一个数字 public boolean likeThisName(String thisName) { count = 0; for (Iterator it = client.listIterator(); it.hasNext();) { String temp = (String) it.next(); if (temp.startsWith(thisName) == true) { count++; } } if (count > 0) return true; else return false; } public static void handleMessage(String msg) { // System.out.println("服务端收到信息:" + msg); nioServer.solveMsg(msg); } }
### 回答1: Java NIO(New IO)主要用于需要高性能、高可伸缩性、高并发处理能力的场景,例如: 1. 网络编程:Java NIO提供了非阻塞式的网络通信模型,可以使用单线程处理多个并发连接,从而实现高并发网络编程。 2. 大数据处理:Java NIO可以高效地处理大文件的读写操作,通过内存映射文件的方式,避免了频繁的用户空间和内核空间之间的数据传输,提高了大数据处理的效率。 3. 实时性要求高的应用:Java NIO提供了选择器(Selector)机制,可以实现非阻塞式的I/O操作,并通过轮询方式检测I/O事件,从而及时响应并处理事件,满足实时性要求高的应用场景。 4. 多线程编程:Java NIO提供了基于缓冲区(Buffer)的操作方式,可以避免多线程操作时的线程安全问题,提高多线程编程的效率和可靠性。 5. 分布式应用:Java NIO可以通过非阻塞式的网络通信模型和多路复用技术,实现高并发的分布式应用系统,提高了系统的可伸缩性和性能。 ### 回答2: Java NIO(New I/O)是Java编程语言的一种新的I/O API,用于处理非阻塞的I/O操作。相对于传统的I/O,Java NIO提供了更高效、更灵活的方式来处理输入和输出。 Java NIO适用于许多场景,包括以下几个方面: 1. 网络编程:Java NIO可以轻松处理高并发的网络连接。使用Java NIO的Selector和Channel,可以同时管理多个网络连接,非阻塞地进行读写操作,并实现更高效的网络通信。 2. 高性能服务器:Java NIO提供了更好的性能,特别适用于需要处理大量连接和并发请求的服务器应用程序。通过使用Selector,可以同时处理多个连接,而无需为每个连接创建一个线程,从而减小了系统开销。 3. 文件操作:Java NIO提供了更快速、更灵活的文件操作方式。通过使用FileChannel,可以直接在文件中进行读写操作,而不需要通过中间缓冲区来处理数据。 4. 客户端/服务器通信:Java NIO可以用于实现高效的客户端/服务器通信。通过使用Selector,可以同时处理多个客户端连接,并且可以通过非阻塞地读写操作,提高了通信的效率。 5. 多线程任务调度:Java NIO的Selector机制可以用于多线程任务的调度。通过Selector将多个Channel注册到一个Selector上,可以更好地管理和调度多个任务的执行。 总之,Java NIO可以用在许多需要高性能和高并发的场景中,特别适合网络编程和处理大量并发连接的服务器应用程序。它提供了更高效、更灵活的方式来处理输入和输出,是现代Java应用程序开发中的重要组件。 ### 回答3: Java NIO(New I/O)是在Java 1.4版本中引入的一种替代传统Java IO的新的I/O处理方式。相比传统的Java IO,Java NIO提供了更高效、更灵活的I/O操作,适用于以下几个场景: 1. 高性能网络编程:Java NIO的非阻塞I/O模型使得可以同时处理多个客户端连接,适用于构建高性能的服务器程序,比如聊天服务器、游戏服务器、Web服务器等。 2. 大规模数据传输:Java NIO的零拷贝特性可以在数据传输过程中避免不必要的数据复制,提高传输性能。适用于大规模文件传输、内容分发网络(CDN)等场景。 3. 多路复用器:Java NIO中的Selector可以同时监控多个通道的状态,当一个或多个通道就绪时,可以及时进行相应的操作,实现高效的事件驱动编程。适用于实现高并发、高吞吐量的服务器程序。 4. 文件操作:Java NIO提供了更强大、更灵活的文件操作方式,包括读写文件、文件锁、内存映射文件等操作。适用于处理大文件、日志文件、数据库事务日志等场景。 5. 数据库操作:Java NIO可以结合数据库连接池进行高效的数据库操作,提高数据库读写性能。适用于需要频繁与数据库进行交互的应用程序。 总之,Java NIO适用于需要高效、高并发的I/O处理场景,可以帮助开发者更好地利用系统资源,提高应用程序的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值