`
love5845
  • 浏览: 1548 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

nio 聊天窗口

阅读更多

 服务器

package com.ww.server;

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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import com.ww.dao.UsersData;
import com.ww.entity.Users;


public class Server implements Runnable{
	
	//选择器
	private Selector selector;
	
	//选择key
	private SelectionKey sscKey;
	
	//服务器开关
	private boolean isOpen;
	
	//用户集合
	private List<Users> users;
	
	//用户上线列表
	private Vector<String> userNames;
	
	public Server(int port)
	{
		isOpen = true;
		users = UsersData.dataUsers();
		userNames = new Vector<String>();
		init(port);
	}
	
	
	@Override
	public void run() 
	{
		try {
			while(isOpen)
			{
				//接收信息的数量
				int result = selector.select();
				if(result > 0)
				{
					for (Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); iterator.hasNext();) 
					{
						SelectionKey key = (SelectionKey) iterator.next();
						iterator.remove();
						//判断是否是接收状态
						if(key.isAcceptable())
						{
							System.out.println("==========客户端开启==========");
							getConn(key);
						}
						//判断是否是读取状态
						else if(key.isReadable())
						{
							System.out.println("=============读取=============");
							ReadMsg(key);
						}
						//判断是否是写入状态
						else if(key.isWritable())
						{
							System.out.println("=============写入=============");
							WriteMsg(key);
						}
						
					}
				}
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	//初始化服务器
	private void init(int port)
	{
		try {
			//开启选择器
			selector = Selector.open();
			//开启ServerSocket
			ServerSocketChannel ssc = ServerSocketChannel.open();
			//设置非阻塞模式
			ssc.configureBlocking(false);
			//设置端口
			ssc.socket().bind(new InetSocketAddress(port));
			//注册到选择器里并设置为接收状态
			sscKey = ssc.register(selector,SelectionKey.OP_ACCEPT);
			System.out.println("==========开启服务器==========");
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//获取连接
	private void getConn(SelectionKey key) throws IOException
	{
		//获取ServerSocket
		ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
		//设置Socket
		SocketChannel sc = ssc.accept();
		//设置非阻塞模式
		sc.configureBlocking(false);
		//注册到选择器里并设置为读取状态
		sc.register(selector, SelectionKey.OP_READ);
	}
	
	//读取信息
	private void ReadMsg(SelectionKey key) throws IOException
	{
		//获取到Socket
		SocketChannel sc = (SocketChannel)key.channel();
		ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
		buffer.clear();
		StringBuffer sb = new StringBuffer();
		//获取字节长度
		int count = sc.read(buffer);
		if( count > 0 )
		{
			buffer.flip();
			sb.append(new String(buffer.array(), 0, count));
		}
		Object obj = (Object)sb.toString();
		if(obj.toString().indexOf("-")!= -1)
		{
			//获取用户名
			String userName = obj.toString().substring(0, obj.toString().indexOf("-"));
			//获取用户密码
			String userPass = obj.toString().substring(obj.toString().indexOf("-") + 1);
			
			boolean isTrue = false;
			//判断用户是否存在
			for (int i = 0; i < users.size(); i++) {
				if(users.get(i).getUserName().equals(userName) && users.get(i).getUserPass().equals(userPass))
				{
					System.out.println("========" + userName + "登录成功========");
					isTrue = true;
					userNames.addElement(userName);
					KeyAttach(key,"true");
					break;
				}
				isTrue = false;
			}
			
			//用户不存在
			if(!isTrue)
			{
				System.out.println("========" + userName + "登录失败========");
				KeyAttach(key,"false");
			}
		}
		else if(obj.toString().equals("open"))
		{
			System.out.println("=========开启聊天窗口=========");
			//给都有的用户返回用户列表
			AllKeysAttach(key,userNames);
		}
		else if( obj.toString().indexOf("exit_") != -1 )
		{
			String userName = obj.toString().substring(5);
			userNames.removeElement(userName);
			System.out.println("========" + userName + "退出窗体========");
			KeyAttach(key,"close");
			OtherKeysAttach(key,userNames);
		}
		else
		{
			//获取用户名
			String userName = obj.toString().substring(0,obj.toString().indexOf("^"));
			//获取信息
			String mess = obj.toString().substring(obj.toString().indexOf("^")+1);
			//获取发信时间
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			String dateTime = dateFormat.format(new Date());
			//设置信息
			String mss = userName + " " + dateTime + "\n" + mess + "\n";
			//给都有的用户返回聊天信息
			AllKeysAttach(key,mss);
		}
		
	}
	
	//所有client改成写入状态
	private void AllKeysAttach(SelectionKey key,Object obj)
	{
		for (Iterator<SelectionKey> iterator = key.selector().keys().iterator(); iterator.hasNext();) 
		{
			SelectionKey selKey = (SelectionKey) iterator.next();
			//判断不是Server key;
			if( selKey != sscKey )
			{
				selKey.attach(obj);
				//把其他client改成可写状态
				selKey.interestOps( selKey.interestOps() | SelectionKey.OP_WRITE );
			}
		}
	}
	
	//把其他客户改成写入状态
	private void OtherKeysAttach(SelectionKey key,Object obj)
	{
		for (Iterator<SelectionKey> iterator = key.selector().keys().iterator(); iterator.hasNext();) 
		{
			SelectionKey selKey = (SelectionKey) iterator.next();
			//判断不是本生client key和Server key;
			if( selKey != sscKey && selKey != key )
			{
				selKey.attach(obj);
				//把其他client改成可写状态
				selKey.interestOps( selKey.interestOps() | SelectionKey.OP_WRITE );
			}
		}
	}
	
	//自身改成写入状态
	private void KeyAttach(SelectionKey key,Object obj)
	{
		key.attach(obj);
		key.interestOps(SelectionKey.OP_WRITE);
	}
	
	//发送信息
	private void WriteMsg(SelectionKey key) throws IOException
	{
		//获取到Socket
		SocketChannel sc = (SocketChannel)key.channel();
		//获取附属值
		Object obj = key.attachment();
		//把附属值设为空
		key.attach("");
		//发送信息
		sc.write(ByteBuffer.wrap(obj.toString().getBytes()));
		if(obj.toString().equals("close") || obj.toString().equals("false"))
		{
			key.cancel();
			sc.socket().close();
			sc.close();
			System.out.println("==========客户端关闭==========");
			return;
		}
		//设置为读取状态
		key.interestOps(SelectionKey.OP_READ);
	}
	
	public static void main(String[] args) 
	{   
		Server server = new Server(8001);
		new Thread(server).start();
	}
}

 

  客户端界面

       1.登录界面

package com.ww.frame;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

import com.ww.biz.ClientServerBIz;
import com.ww.frame.ChatFrame;

public class LoginFrame {
	
	private JLabel 
		lblTitle = new JLabel("山寨版QQ"),
		lblUserName = new JLabel("用户名:"),
		lblPassword = new JLabel("密     码:");
	
	private JTextField 
		txtUserName = new JTextField(15),
		txtPassword = new JTextField(15);
	
	private JButton
		btnSub = new JButton("提交"),
		btnRes = new JButton("取消");
	
	private JFrame
		aFrame = new JFrame("登录山寨QQ");
	
	private ClientServerBIz clientBiz;
	public LoginFrame()
	{
		into();
	}
	
	private void into()
	{
		aFrame.setLayout(null);
		aFrame.setBounds(300, 300, 200, 180);
		lblTitle.setBounds(45, 10, 100, 40);
		lblTitle.setForeground(new Color(120, 120, 120));
		lblTitle.setFont(new Font("山寨版QQ", 1, 20));
		aFrame.add(lblTitle);
		lblUserName.setBounds(10, 50, 80, 20);
		aFrame.add(lblUserName);
		lblPassword.setBounds(10, 80, 80, 20);
		aFrame.add(lblPassword);
		txtUserName.setBounds(65, 50, 120, 20);
		aFrame.add(txtUserName);
		txtPassword.setBounds(65, 80, 120, 20);
		aFrame.add(txtPassword);
		btnSub.setBounds(10, 110, 80, 25);
		aFrame.add(btnSub);
		btnRes.setBounds(100, 110, 80, 25);
		aFrame.add(btnRes);
		
		btnSub.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String userInfo = txtUserName.getText() + "-" + txtPassword.getText();
				try {
					clientBiz = new ClientServerBIz();
					clientBiz.sendToServer(userInfo);
					Object obj = clientBiz.sendToClient();
					System.out.println(obj.toString());
					if (Boolean.parseBoolean(obj.toString()))
					{
						ChatFrame cf = new ChatFrame(clientBiz,txtUserName.getText());
						cf.show();
						aFrame.setVisible(false);
					}
					else
					{
						System.out.println("用户不存在或密码错误!");
					}
				} catch (IOException e1) {
					e1.printStackTrace();
				} catch (ClassNotFoundException e1) {
					e1.printStackTrace();
				}
			}
		});
		
		btnRes.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		
		aFrame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}	
		});
	}
	
	public void show()
	{
		aFrame.setVisible(true);
	} 
	
	public static void main(String[] args) {
		LoginFrame login = new LoginFrame();
		login.show();
	}

}

 

       2.聊天界面

package com.ww.frame;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.ww.biz.ClientServerBIz;

public class ChatFrame {
	
	//文本框
	private JTextArea
		readContext = new JTextArea(18,30),//显示信息
		writeContext = new JTextArea(6,30);//发送信息
	
	//列表框
	private DefaultListModel modle = new DefaultListModel();//列表模型
	private JList list = new JList(modle);//列表
	
	//按钮
	private JButton 
		btnSub = new JButton("提交"),//提交按钮
		btnRes = new JButton("取消");//取消按钮
	
	//窗体界面
	private JFrame aFrame = new JFrame("ChatFrame");
	
	//用户名
	private String userName;
	
	//Client业务类
	private ClientServerBIz userBiz;
	
	//设置线程是否运行
	private boolean isConntext = false;
	
	//构造方法
	public ChatFrame(ClientServerBIz clientBiz,String userName)
	{
		//获取用户名
		this.userName = userName;
		userBiz = clientBiz;
		//开启线程
		isConntext = true;
		new Thread(new ctUsers()).start();	
	}
	
	//初始化界面
	private void init() throws IOException, ClassNotFoundException
	{
		aFrame.setLayout(null);
		aFrame.setTitle(userName+" 聊天窗口");
		aFrame.setSize(500, 500);
		aFrame.setLocation(400, 200);
		readContext.setBounds(10, 10, 320, 285);
		readContext.setEditable(false);
		writeContext.setBounds(10, 305, 320, 100);
		list.setBounds(340, 10, 140, 445);
		aFrame.add(readContext);
		aFrame.add(writeContext);
		aFrame.add(list);
		btnSub.setBounds(150, 415, 80, 30);
		btnRes.setBounds(250, 415, 80, 30);
		
		//frame的关闭按钮事件
		aFrame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				isConntext = false;
				//发送关闭信息
				userBiz.sendToServer("exit_" + userName);
				System.exit(0);
			}
		});

		//提交按钮事件
		btnSub.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//发送信息
				userBiz.sendToServer(userName + "^" + writeContext.getText());
				writeContext.setText(null);
			}
		});
		
		//关闭按钮事件
		btnRes.addActionListener(new ActionListener() {	
			@Override
			public void actionPerformed(ActionEvent e) {
				isConntext = false;
				//发送关闭信息
				userBiz.sendToServer("exit_" + userName);
				System.exit(0);
			}
		});
		
		
		list.addListSelectionListener(new ListSelectionListener() {	
			@Override
			public void valueChanged(ListSelectionEvent e) {
				JOptionPane.showMessageDialog(null,list.getSelectedValue().toString());
			}
		});
		
		aFrame.add(btnSub);
		aFrame.add(btnRes);
		aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	//界面显示
	public void show() throws IOException, ClassNotFoundException
	{
		init();
		aFrame.setVisible(true);
		userBiz.sendToServer("open");
	}
	
	class ctUsers extends Thread
	{
		public void run() 
		{
			while(isConntext)
			{
				//获取服务器传过的值
				Object obj = userBiz.sendToClient();
				
				//判断值是否有空
				if(obj != null)
				{
					
					if(obj.toString().indexOf("[") != -1 && obj.toString().lastIndexOf("]") != -1)
					{
						obj = obj.toString().substring(1, obj.toString().length()-1);
						String [] userNames = obj.toString().split(",");
						modle.removeAllElements();
						for (int i = 0; i < userNames.length; i++) {
							modle.addElement(userNames[i].trim());
						}
					}
					else
					{
						String str = readContext.getText() + obj.toString();
						readContext.setText(str);
					}
				}
			}
		}
	}
}

 

 客户端业务类

package com.ww.biz;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;


public class ClientServerBIz {
	
	private SocketChannel sc;
	public ClientServerBIz() throws IOException
	{
		sc = SocketChannel.open();
		sc.configureBlocking(false);
		sc.connect(new InetSocketAddress("localhost",8001));
	}

	//发送信息到服务器
	public void sendToServer(Object obj)
	{
		try {
			while(!sc.finishConnect())
			{}
			sc.write(ByteBuffer.wrap(obj.toString().getBytes()));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//获取服务器信息传递信息到客户端
	public Object sendToClient()
	{
		ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
		buffer.clear();
		StringBuffer sb = new StringBuffer();
		int count = 0;
		Object obj = null;
		try {
			//获取字节长度
			Thread.sleep(100);
			while ((count = sc.read(buffer)) > 0) {
				sb.append(new String(buffer.array(), 0, count));
            }
			if( sb.length() > 0 )
			{
				obj = sb.toString();
				if("close".equals(sb.toString()))
				{
					obj = null;
					sc.close();
					sc.socket().close();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return obj;
	}
}

 数据源

package com.ww.dao;

import java.util.ArrayList;
import java.util.List;

import com.ww.entity.Users;

public class UsersData {
	public static List<Users> dataUsers()
	{
		List<Users> users = new ArrayList<Users>();
		Users user1 = new Users("tiantian","123456");
		Users user2 = new Users("dongdong","123456");
		Users user3 = new Users("xiaoxiao","123456");
		Users user4 = new Users("mingming","123456");
		users.add(user1);
		users.add(user2);
		users.add(user3);
		users.add(user4);
		return users;
	}
}

 

实体

package com.ww.entity;

import java.io.Serializable;

public class Users implements Serializable{
	private String userName;
	private String userPass;
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserPass() {
		return userPass;
	}
	public void setUserPass(String userPass) {
		this.userPass = userPass;
	}
	public Users(String userName,String userPass)
	{
		this.userName = userName;
		this.userPass = userPass;
	}
}

 

各位大侠小弟有地方写的不好的地方请指点一二!

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    java nio 聊天室源码

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

    java nio聊天室源码

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

    基于NIO的聊天室

    基于NIO的聊天室

    基于nio的简易聊天室

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

    UDP NIO聊天系统

    UDP NIO聊天系统,基于UDP通道,NIO,包括服务器端和客户端

    java NIO socket聊天

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

    NIO聊天室代码

    NIO框架实现的简单聊天室,分为客户端和服务器端,为大家了解NIO作为一个参考

    基于NIO的简易聊天室(命令行)源码.rar

    基于NIO编写的聊天室,命令行运行,分server,client,config三个包,分别存放服务器端,客户端,以及一些端口信息的配置类。

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

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

    非GUI聊天室基于javaNIO

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

    JAVA NIO 聊天室程序

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

    基于NIO的多线程聊天系统

    基于NIO的多线程聊天系统,代码很少,很经典,51CTO网站上的代码。有登陆和聊天界面。代码结构层次清晰,系统只有6个类。

    Java NIO 聊天室 JSwing

    MyDialog md=new MyDialog(LoginFrame.this,"提示窗口","错误!","用户名或密码错误.\n登陆失败"); md.showDialog(); } } else { if(nameLength==0) { MyDialog md=...

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

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

    java NIO socket聊天室

    使用NIO socket不需要多线程来处理多个连接的请求,效率非常高 可以作为NIO socket入门的例子,Reactor模式,重点理解key.attach, jar文件里包含了源代码 1,运行server.bat启动服务器,可以打开编辑,修改端口号 ...

    基于NIO的多人聊天室项目

    相比于上次的基于BIO的多人聊天室的线程数量大幅度减少。 一个线程用于监听客户端的到达,两个线程池分别负责客户端 消息的 读 和写。 另外两个线程 负责 readSelector 和writeSelector 的监听。 但是仅仅是对 ...

    基于NIO的Java聊天室2

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

    用Netty实现NIO Socket聊天系统示例

    用Netty实现NIO Socket聊天系统示例 ,完整代码,已开源,希望大家多提意见。

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

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

Global site tag (gtag.js) - Google Analytics