java聊天室源码二代.docx
《java聊天室源码二代.docx》由会员分享,可在线阅读,更多相关《java聊天室源码二代.docx(15页珍藏版)》请在冰豆网上搜索。
java聊天室源码二代
java聊天室源码(二代)
部门:
xxx
时间:
xxx
制作人:
xxx
整理范文,仅供参考,可下载自行修改
JAVA聊天室<二代)代码仅为原来的一半!
性能进一步提升,性能允许的基础上可连接无数客户端,改进了下线CPU占有暴增情况,实现指定人员聊天功能。
。
来源:
管天阳的日志
登录桌面
登录后用户列表可以显示
可指定人员单独聊天
上线客户端提醒
退出时列表可显示,每个客户端的用户项也将消失。
。
下面是代码:
1.服务器:
packagecom.zzk。
importjava.awt.BorderLayout。
importjava.awt.Frame。
importjava.awt.Image。
importjava.awt.MenuItem。
importjava.awt.PopupMenu。
importjava.awt.SystemTray。
importjava.awt.TrayIcon。
importjava.awt.event.ActionEvent。
importjava.awt.event.ActionListener。
importjava.awt.event.MouseAdapter。
importjava.awt.event.MouseEvent。
importjava.awt.event.WindowAdapter。
importjava.awt.event.WindowEvent。
importjava.io.IOException。
importjava.io.ObjectInputStream。
importjava.io.PrintWriter。
import.ServerSocket。
import.Socket。
import.URL。
importjava.util.Hashtable。
importjava.util.Iterator。
importjava.util.Set。
importjava.util.Vector。
importjavax.swing.ImageIcon。
importjavax.swing.JFrame。
importjavax.swing.JScrollPane。
importjavax.swing.JTextArea。
b5E2RGbCAP
publicclassChatServerFrameextendsJFrame{
privateJTextAreata_info。
privateServerSocketserver。
//声明ServerSocket对象
privateSocketsocket。
//声明Socket对象socket
privateHashtablemap=newHashtable(>。
//用于存储连接到服务器的用户和客户端套接字对象
publicvoidcreateSocket(>{
try{
server=newServerSocket(1982>。
//创建服务器套接字对象
while(true>{
ta_info.append("等待新客户连接......\n">。
socket=server.accept(>。
//获得套接字对象
ta_info.append("客户端连接成功。
"+socket+"\n">。
newServerThread(socket>.start(>。
//创建并启动线程对象
}
}catch(IOExceptione>{
e.printStackTrace(>。
}
}
classServerThreadextendsThread{
Socketsocket。
publicServerThread(Socketsocket>{
this.socket=socket。
}
publicvoidrun(>{
try{
ObjectInputStreamins=newObjectInputStream(socket
.getInputStream(>>。
while(true>{
Vectorv=null。
try{
v=(Vector>ins.readObject(>。
}catch(ClassNotFoundExceptione>{
e.printStackTrace(>。
}
if(v!
=null&&v.size(>>0>{
for(inti=0。
i。
i++>{
Stringinfo=(String>v.get(i>。
//读取信息
Stringkey=""。
if(info.startsWith("用户:
">>{//添加登录用户到客户端列表
key=info.substring(3,info.length(>>。
//获得用户名并作为键使用
map.put(key,socket>。
//添加键值对
Setset=map.keySet(>。
//获得集合中所有键的Set视图
IteratorkeyIt=set.iterator(>。
//获得所有键的迭代器
while(keyIt.hasNext(>>{
StringreceiveKey=keyIt.next(>。
//获得表示接收信息的键
Sockets=map.get(receiveKey>。
//获得与该键对应的套接字对象
PrintWriterout=newPrintWriter(s
.getOutputStream(>,true>。
//创建输出流对象
IteratorkeyIt1=set.iterator(>。
//获得所有键的迭代器
while(keyIt1.hasNext(>>{
StringreceiveKey1=keyIt1.next(>。
//获得键,用于向客户端添加用户列表
out.println(receiveKey1>。
//发送信息
out.flush(>。
//刷新输出缓冲区
}
}
}elseif(info.startsWith("退出:
">>{
key=info.substring(3>。
//获得退出用户的键
map.remove(key>。
//删除键值对
Setset=map.keySet(>。
//获得集合中所有键的Set视图
IteratorkeyIt=set.iterator(>。
//获得所有键的迭代器
while(keyIt.hasNext(>>{
StringreceiveKey=keyIt.next(>。
//获得表示接收信息的键
Sockets=map.get(receiveKey>。
//获得与该键对应的套接字对象
PrintWriterout=newPrintWriter(s
.getOutputStream(>,true>。
//创建输出流对象
out.println("退出:
"+key>。
//发送信息
out.flush(>。
//刷新输出缓冲区
}
}else{//转发接收的消息
key=info.substring(info.indexOf(":
发送给:
">+5,
info.indexOf(":
的信息是:
">>。
//获得接收方的key值,即接收方的用户名<因为substring起始索引包括,结尾索引不包括所以要+5)
StringsendUser=info.substring(0,info
.indexOf(":
发送给:
">>。
//获得发送方的key值,即发送方的用户名
Setset=map.keySet(>。
//获得集合中所有键的Set视图
IteratorkeyIt=set.iterator(>。
//获得所有键的迭代器
while(keyIt.hasNext(>>{
StringreceiveKey=keyIt.next(>。
//获得表示接收信息的键
if(key.equals(receiveKey>&&!
sendUser.equals(receiveKey>>{//与接受用户相同,但不是发送用户
Sockets=map.get(receiveKey>。
//获得与该键对应的套接字对象
PrintWriterout=newPrintWriter(s.getOutputStream(>,true>。
//创建输出流对象
out.println("MSG:
"+info>。
//发送信息
out.flush(>。
//刷新输出缓冲区
}
}
}
}
}
}
}catch(IOExceptione>{
ta_info.append(socket+"已经退出。
\n">。
}
}
}
publicstaticvoidmain(Stringargs[]>{
ChatServerFrameframe=newChatServerFrame(>。
frame.setVisible(true>。
frame.createSocket(>。
}
/**
*Createtheframe
*/
publicChatServerFrame(>{
super(>。
addWindowListener(newWindowAdapter(>{
publicvoidwindowIconified(finalWindowEvente>{
setVisible(false>。
}
}>。
setTitle("聊天室服务器端">。
setBounds(100,100,385,266>。
finalJScrollPanescrollPane=newJScrollPane(>。
getContentPane(>.add(scrollPane,BorderLayout.CENTER>。
ta_info=newJTextArea(>。
scrollPane.setViewportView(ta_info>。
//托盘
if(SystemTray.isSupported(>>{//判断是否支持系统托盘
URLurl=ChatServerFrame.class.getResource("server.png">。
//获取图片所在的URL
ImageIconicon=newImageIcon(url>。
//实例化图像对象
Imageimage=icon.getImage(>。
//获得Image对象
TrayIcontrayIcon=newTrayIcon(image>。
//创建托盘图标
trayIcon.addMouseListener(newMouseAdapter(>{//为托盘添加鼠标适配器
publicvoidmouseClicked(MouseEvente>{//鼠标事件
if(e.getClickCount(>==2>{//判断是否双击了鼠标
showFrame(>。
//调用方法显示窗体
}
}
}>。
trayIcon.setToolTip("系统托盘">。
//添加工具提示文本
PopupMenupopupMenu=newPopupMenu(>。
//创建弹出菜单
MenuItemexit=newMenuItem("退出">。
//创建菜单项
exit.addActionListener(newActionListener(>{//添加事件监听器
publicvoidactionPerformed(finalActionEventarg0>{
System.exit(0>。
//退出系统
}
}>。
popupMenu.add(exit>。
//为弹出菜单添加菜单项
trayIcon.setPopupMenu(popupMenu>。
//为托盘图标加弹出菜弹
SystemTraysystemTray=SystemTray.getSystemTray(>。
//获得系统托盘对象
try{
systemTray.add(trayIcon>。
//为系统托盘加托盘图标
}catch(Exceptione>{
e.printStackTrace(>。
}
}
}
publicvoidshowFrame(>{
this.setVisible(true>。
//显示窗体
this.setState(Frame.NORMAL>。
}
}p1EanqFDPw
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////DXDiTa9E3d
2.客户端:
packagecom.zzk。
importjava.awt.BorderLayout。
importjava.awt.Dimension。
importjava.awt.EventQueue。
importjava.awt.Font。
importjava.awt.Frame。
importjava.awt.Image。
importjava.awt.MenuItem。
importjava.awt.PopupMenu。
importjava.awt.SystemTray。
importjava.awt.TrayIcon。
importjava.awt.event.ActionEvent。
importjava.awt.event.ActionListener。
importjava.awt.event.MouseAdapter。
importjava.awt.event.MouseEvent。
importjava.io.BufferedReader。
importjava.io.IOException。
importjava.io.InputStreamReader。
importjava.io.ObjectOutputStream。
import.Socket。
import.URL。
import.UnknownHostException。
importjava.text.DateFormat。
importjava.util.Date。
importjava.util.Vector。
importjavax.swing.DefaultComboBoxModel。
importjavax.swing.ImageIcon。
importjavax.swing.JButton。
importjavax.swing.JFrame。
importjavax.swing.JLabel。
importjavax.swing.JList。
importjavax.swing.JOptionPane。
importjavax.swing.JPanel。
importjavax.swing.JScrollPane。
importjavax.swing.JSplitPane。
importjavax.swing.JTextArea。
importjavax.swing.JTextField。
RTCrpUDGiT
publicclassChatClientFrameextendsJFrame{
privateJTextFieldtf_newUser。
privateJListuser_list。
privateJTextAreata_info。
privateJTextFieldtf_send。
privateObjectOutputStreamout。
//声明输出流对象
privatebooleanloginFlag=false。
//为true时表示已经登录,为false时表示未登录
publicstaticvoidmain(Stringargs[]>{
EventQueue.invokeLater(newRunnable(>{
publicvoidrun(>{
try{
ChatClientFrameframe=newChatClientFrame(>。
frame.setVisible(true>。
frame.createClientSocket(>。
//调用方法创建套接字对象
}catch(Exceptione>{
e.printStackTrace(>。
}
}
}>。
}
publicvoidcreateClientSocket(>{
try{
Socketsocket=newSocket("localhost",1982>。
//创建套接字对象
out=newObjectOutputStream(socket.getOutputStream(>>。
//创建输出流对象
newClientThread(socket>.start(>。
//创建并启动线程对象
}catch(UnknownHostExceptione>{
e.printStackTrace(>。
}catch(IOExceptione>{
e.printStackTrace(>。
}
}
classClientThreadextendsThread{
Socketsocket。
publicClientThread(Socketsocket>{
this.socket=socket。
}
publicvoidrun(>{
try{
BufferedReaderin=newBufferedReader(newInputStreamReader(
socket.getInputStream(>>>。
//创建输入流对象
DefaultComboBoxModelmodel=(DefaultComboBoxModel>user_list
.getModel(>。
//获得列表框的模型
while(true>{
Stringinfo=in.readLine(>.trim(>。
//读取信息
if(!
info.startsWith("MSG:
">>{//接收到的不是消息
if(info.startsWith("退出:
">>{//接收到的是退出消息
model.removeElement(info.substring(3>>。
//从用户列表中移除用户
}else{//接收到的是登录用户
booleanitemFlag=false。
//标记是否为列表框添加列表项,为true不添加,为false添加
for(inti=0。
i。
i++>{//对用户列表进行遍历
if(info.equals((String>model.getElementAt(i>>>{//如果用户列表中存在该用户名
itemFlag=true。
//设置为true,表示不添加到用户列表
break。
//结束for循环
}
}
if(!
itemFlag>{
model.addElement(info>。
//将登录用户添加到用户列表
}
}
}else{//如果获得的是消息,则在文本域中显示接收到的消息
DateFormatdf=DateFormat.getDateInstance(>。
//获得DateFormat实例
StringdateString=df.format(newDate(>>。
//格式化为日期
df=DateFormat.getTimeInstance(DateFormat.MEDIUM>。
//获得DateFormat实例
StringtimeString=df.format(newDate(>>。
//格式化为时间
StringsendUser=info.substring(4,info.indexOf(":
发送给:
">>。
//获得发送信息的用户
StringreceiveInfo=info.substring(info.indexOf(":
的信息是:
">+6>。
//获得接收到的信息
ta_info.append(""+sendUser+""+dateString+""+timeString+"\n"+receiveInfo+"\n">。
//在文本域中显示信息
ta_info.setSelectionStart(ta_info.getText(>.length(>-1>。
//设置选择起始位置
ta_info.setSelectionEnd(ta_info.getText(>.length(>>。
//设置选择的结束位置
tf_send.requestFocus(>。
//使发送信息文本框获得焦点
}
}
}catch(IOExceptione>{
e.printStackTrace(>。
}
}
}
privatevoidsend(>{
if(!
loginFlag>{
JOptionPane.showMessageDialog(null,"请先登录。
">。
return。
//如果用户没登录则返回
}
StringsendUserName=tf_newUser.getText(>.trim(>。
//获得登录用户名
Stringinfo=tf_send.getText(>。
//获得输入的发送信息
if(info.equals("">>{
return。
//如果没输入信息则返回,即不发送
}
Vectorv=newVector(>。
//创建向量对象,用于存储发送的消息
Object[]receiveUserNames=user_list.getSelectedValues(>。
//获得选择的用户数组
if(receiveUserNames.length<=0>{
return。
//如果没选择用户则返回
}
for(inti=0。
i