`
love5845
  • 浏览: 1571 次
  • 性别: 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;
	}
}

 

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

分享到:
评论
发表评论

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

相关推荐

    基于nio的简易聊天室

    在GUI设计时,可能会使用JFrame作为主窗口,JTextArea显示聊天记录,JTextField用于输入消息,以及JButton触发发送操作。 5. **线程管理**: 在服务器端,为了处理多个并发的客户端连接,可能需要设计合理的线程...

    JAVA NIO 聊天室程序

    在这个聊天室程序中,JSwing用于创建用户界面,如聊天窗口、用户列表、输入框和发送按钮等。 3. **NIO在聊天室中的应用** - 在聊天室服务端,NIO的选择器可以监听多个客户端连接,一旦有新的连接请求或数据传输,...

    Java NIO 聊天室 JSwing

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

    QQ聊天窗口 模仿MSN 但是QQ可以用

    QQ聊天窗口模仿MSN的设计风格,但仍然保持了QQ的基本功能,这一设计体现了软件开发中的兼容性和创新性。在本文中,我们将深入探讨QQ聊天窗口如何借鉴MSN的界面元素,同时保持其自身特色,并重点关注JAVA技术在实现这...

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

    Java的窗体界面通常由`java.awt`和`javax.swing`包提供,可能使用`JFrame`作为主窗口,`JTextArea`显示聊天历史,`JTextField`供用户输入消息,` JButton`触发发送操作。画板功能可能涉及`java.awt.Canvas`或`javax....

    Java+Swing聊天室

    开发者通常会把聊天窗口和输入区域分别封装到JPanel中,然后添加到JFrame上。 3. **JTextComponent**:在这个聊天室中,可能使用了JTextArea作为用户输入消息的地方,而JLabel或者JScrollPane可能用于展示历史消息...

    nio+bio+netty+fx.zip

    在本项目中,JavaFX被用来构建聊天室的前端界面,用户可以通过文本框输入消息,并通过按钮触发发送事件,接收的消息则会在聊天窗口中显示出来。 项目中的`nio+bio+netty+fx`可能包含以下文件: - `BioChatServer....

    java 聊天程序源码

    Java聊天程序源码是一个用于学习和理解网络编程和并发处理的宝贵资源,尤其对于初学者或希望提升Java技能的开发者而言。...同时,它也可以作为你学习其他高级Java技术,如NIO(非阻塞I/O)或WebSocket的起点。

    Java即时通讯聊天室

    这通常涉及到客户端之间的直接TCP连接,发送端将消息封装成数据包,通过网络发送到接收端,接收端接收到数据后解包并显示在聊天窗口。 3. **群聊**:群聊功能使得多用户可以同时参与同一对话。实现群聊通常需要...

    基于Java的P2P多用户在线聊天室项目源码

    在用户交互方面,项目可能使用了Swing或JavaFX等图形用户界面(GUI)库来创建聊天窗口和控制面板,提供友好的用户体验。用户可以通过输入框发送消息,聊天窗口实时显示收到的消息。此外,可能还包含了用户管理功能,...

    JavaSwing的QQ聊天系统

    1. **Swing组件**:Swing提供了一系列的组件,如JFrame(主窗口)、JLabel(标签)、JButton(按钮)、JTextField(文本字段)、JTextArea(文本区域)和JOptionPane(对话框)等,这些组件用于构建聊天窗口、输入框...

    java聊天室(绝对经典)

    第三种风格的聊天室可能采用了异步编程模型,比如Java 8引入的CompletableFuture或者NIO.2框架。这种实现方式可以更有效地管理并发,使得服务器能更好地应对高并发场景。 在"JAVA聊天室程序.rar"中,你可能会看到一...

    java开发的聊天工具

    开发者可以使用这些库创建聊天窗口,包括输入框、发送按钮、聊天历史记录视图等元素。为了提供良好的交互体验,UI设计需遵循人机工程学原则,并考虑响应式设计,以适应不同屏幕尺寸。 5. **安全性**:Java提供了...

    java Swing 聊天源码

    在Swing界面上,用户可以看到聊天窗口、输入框以及发送按钮等元素,这些元素的交互逻辑都是由Swing组件和事件处理机制来实现的。 项目描述中提到这只是一个兴趣爱好项目,意味着可能没有涵盖完整的功能,例如用户...

    一款简单的智能聊天系统

    1. **Java图形化界面**:Java Swing是Java GUI的主要实现之一,它提供了诸如按钮、文本框、滚动条等各种组件,可以用来设计聊天窗口、输入框等元素,使用户能够输入和查看聊天信息。 2. **智能聊天系统**:这个系统...

    java聊天系统代码讲解

    - **图形用户界面(GUI)**:Java提供了丰富的GUI库,如Swing和JavaFX,用于创建聊天窗口、输入框、发送按钮等元素。 - **事件监听**:通过事件监听器,当用户点击发送按钮时,触发消息发送功能。 - **网络通信**:...

    Java 客服私聊,聊天室

    3. 开发客户端界面,使用HTML/CSS/JavaScript构建交互式聊天窗口。 4. 实现WebSocket连接,建立服务器与客户端的通信通道。 5. 集成用户认证模块,确保只有合法用户才能参与聊天。 6. 测试各个功能,优化性能,确保...

    聊天室项目设计

    用户界面(UI)是用户与聊天室交互的窗口,通常采用Java Swing或JavaFX库来构建。设计良好的UI应该简洁易用,提供用户登录、注册、发送消息、查看历史记录等功能,并支持表情、图片等多媒体内容。 七、安全考虑 ...

    JAVA聊天室设计与实现

    JAVA的Swing或JavaFX库可以用来创建用户友好的界面,包括输入框、聊天窗口、登录窗口等组件,并通过事件监听处理用户交互。 7. **数据持久化**:尽管这里主要使用XML作为临时存储,但在实际应用中,聊天记录可能...

    java聊天源代码

    Swing是Java的标准GUI库,提供丰富的组件如JFrame(窗口)、JTextArea(文本区域)、JButton(按钮)等,用于显示聊天记录和接收用户输入。JavaFX提供更现代的外观和更强大的2D/3D图形功能。 四、消息序列化与反...

Global site tag (gtag.js) - Google Analytics