服务器端代码:
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import javax.swing.*;
public class Server
{
private static final int PORT=6666;
G_Menu gm=new G_Menu();
private ServerSocket server;
public ArrayList<PrintWriter> list;
public static String user;
public static ArrayList<User> list1=new ArrayList<User>();//定义用户集合
public User uu;
public Server(String user)
{
this.user=user;
}
public void getServer()
{
list =new ArrayList<PrintWriter>();
try{
server=new ServerSocket(PORT);
System.out.println("服务器启动,开始监听......");
while(true)
{
Socket client=server.accept();//接收客户端线程
PrintWriter writer = new PrintWriter(client.getOutputStream());
list.add(writer);
Thread t = new Thread(new Chat(client));
t.start();
}
}catch(Exception ex){
ex.printStackTrace();
}
}
public static void main(String[] args)
{
new Server(user).getServer();
}
class Chat implements Runnable
{
Socket socket;
private BufferedReader br;
private String msg;
private String mssg="";
public Chat(Socket socket)
{
try{
this.socket=socket;
}catch(Exception ex){
ex.printStackTrace();
}
}
public void run()
{
try{
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
while((msg=br.readLine())!=null)
{
if(msg.equals("1008611"))//匹配字符串 显示好友列表
{
msg=br.readLine();
String[] st=msg.split(":");//将用户信息跟消息分隔开
uu=new User(st[0],st[1],socket);//将用户信息添加到User对象中
list1.add(uu);//将对象添加到用户集合
Iterator<User> it=Server.list1.iterator();//遍历用户集合
while(it.hasNext())
{
User use=it.next();
msg=use.getName()+"("+use.getSex()+"):";
mssg+=msg;//将所有的用户信息连接成一个字符串
}
sendMessage("1008611");//显示好友列表匹配标识
sendMessage(mssg);//群发消息
}
else if(msg.equals("10010"))//显示说话消息
{
msg=br.readLine();
System.out.println(msg);
sendMessage("10010");//显示说话信息匹配标识
sendMessage(msg);
}
else if(msg.equals("10086"))//显示进入聊天室
{
msg=br.readLine();
System.out.println(msg);
sendMessage("10086");//进入聊天室匹配标识
sendMessage(msg);
}
else if(msg.equals("841163574"))//私聊
{
msg=br.readLine();
String[] rt=msg.split("1072416535");//把传进来的用户信息跟说话内容分开
System.out.println(rt[1]);//在服务器端显示说话内容
String[] tg=rt[0].split(":");//因为是私聊,传过来两个用户的用户信息,这句作用是再把两个用户信息分开
Iterator<User> iu=Server.list1.iterator();//遍历用户集合
while(iu.hasNext())
{
User se=iu.next();
if(tg[1].equals(se.getName()+"("+se.getSex()+")"))//如果传进来的用户信息跟集合中的用户信息吻合
{
try{
PrintWriter pwriter=new PrintWriter(se.getSock().getOutputStream());//建立用户自己的流
pwriter.println("841163574");//匹配标识
pwriter.println(rt[1]);//向单独用户发送消息
pwriter.flush();
System.out.println(rt[1]);
}catch(Exception ex){
ex.printStackTrace();
}
}
else if(tg[0].equals(se.getName()))//如果传进来的用户信息跟集合中的用户信息吻合
{
try{
PrintWriter pwr=new PrintWriter(se.getSock().getOutputStream());//建立用户自己的流
pwr.println("841163574");//匹配标识
pwr.println(rt[1]);//向单独用户发送消息
pwr.flush();
System.out.println(rt[1]);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
else if(msg.equals("456987"))//下线
{
msg=br.readLine();
System.out.println(msg);//在服务端显示信息
sendMessage("456987");//匹配字符串
sendMessage(msg);//匹配完毕后群发消息
String[] si=msg.split(":");//将传过来的用户名跟信息分隔开
Iterator<User> at=Server.list1.iterator();//遍历用户集合
while(at.hasNext())
{
User sr=at.next();
if(sr.getName().equals(si[0]))//如果传过来的用户名跟用户集合里的用户吻合
{
list1.remove(sr);//将吻合的用户移除
sr.getSock().close();//关闭此用户的socket
}
}
break;
}
else if(msg.equals("123654"))//刷新
{
String mssge="";
Iterator<User> iter=Server.list1.iterator();//遍历用户集合
while(iter.hasNext())
{
User uus=iter.next();
msg=uus.getName()+"("+uus.getSex()+"):";
mssge+=msg;//将所有的用户信息连接成一个字符串
}
sendMessage("123654");//发送刷新匹配标识
sendMessage(mssge);//群发消息
}
}
}catch(IOException ex){
ex.printStackTrace();
}
}
}
public void sendMessage(String message)//群发消息方法
{
try{
for(PrintWriter pw:list)//输出流集合
{
pw.println(message);
pw.flush();
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}
客户端代码:
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
public class Socket_one//客户端
{
private static final int PORT=6666;//端口
public static String user;
public static Socket socket;
public Socket_one(String user)
{
this.user=user;
try{
socket=new Socket("127.0.0.1",PORT);//建立socket连接
System.out.println("【"+user+"】欢迎来到聊天室!");
Thread tt=new Thread(new Recove(socket,user));//建立客户端线程
tt.start();//启动线程
}catch(Exception ex)
{
ex.printStackTrace();
}
}
public static void main(String[] args) throws Exception
{
new Socket_one(user);
}
}
class Recove implements Runnable
{
public String user;
private Socket socket;
private BufferedReader keybord;
public BufferedReader br;
private PrintWriter pw;
private String msg;
G_Menu gm=new G_Menu();
public Recove(Socket socket,String user) throws IOException
{
try{
this.socket=socket;
this.user=user;
}catch(Exception ex){
ex.printStackTrace();
}
}
public void run()
{
try{
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
while((msg=br.readLine())!=null)
{
String message=msg;
if(message.equals("1008611"))//匹配字符串 显示好友列表
{
gm.listModel1.clear();//接收前清空好友列表
gm.jcomb.removeAllItems();//清空JCombox
gm.jcomb.addItem("所有人");
message=br.readLine();
String[] str=message.split(":");//将接收到的所有用户信息分隔开
for(String ss:str)
{
gm.listModel1.addElement(ss);//将所有用户信息添加到好友列表
gm.jcomb.addItem(ss);//将所有用户信息添加到JCombox
}
}
else if(message.equals("841163574"))//私聊
{
message=br.readLine();
System.out.println("收到:"+message);//在服务器端显示私聊消息
gm.jta2.append(message+"\n");//在我的频道显示私聊信息
}
else if(message.equals("10010"))//显示说话消息
{
message=br.readLine();
System.out.println("收到:"+message);//在服务器端显示说话信息
gm.jta1.append(message+"\n");//在公共频道显示说话信息
gm.jta2.append(message+"\n");//在我的频道显示说话信息
}
else if(message.equals("10086"))//显示进入聊天室
{
message=br.readLine();
gm.jta1.append(message+"\n");//在公共频道显示进入聊天室信息
gm.jta2.append(message+"\n");//在我的频道显示进入聊天室信息
}
else if(message.equals("123654"))//刷新
{
gm.listModel1.clear();//将好友列表清空
gm.jcomb.removeAllItems();//将JCombox 清空
gm.jcomb.addItem("所有人");
message=br.readLine();
String[] sr=message.split(":");//将接收到的用户信息分隔开
for(String sst:sr)
{
gm.listModel1.addElement(sst);将刷新后所有用户信息添加到好友列表
gm.jcomb.addItem(sst);//将刷新后所有用户信息添加到JCombox
}
}
else if(message.equals("456987"))//下线
{
message=br.readLine();
gm.jta1.append(message+"\n");//在公共频道显示用户下线信息
gm.jta2.append(message+"\n");//在我的频道显示用户下线信息
}
}
}catch(IOException ex){
ex.printStackTrace();
}
}
}
登陆界面代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import javax.swing.border.*;
class Landen extends Frame implements ActionListener
{
JFrame jf=new JFrame("聊天登陆");
JPanel jp1=new JPanel();
JPanel jp2=new JPanel();
JPanel jp3=new JPanel();
JPanel jp4=new JPanel();
JLabel jl1=new JLabel("姓名:");
JLabel jl2=new JLabel("地址:");
JLabel jl3=new JLabel("端口:");
JRadioButton jrb1=new JRadioButton("男生");
JRadioButton jrb2=new JRadioButton("女生");
JRadioButton jrb3=new JRadioButton("保密");
public JTextField jtf1=new JTextField(10);
public JTextField jtf2=new JTextField(10);
public JTextField jtf3=new JTextField(10);
JButton jb1=new JButton("连接");
JButton jb2=new JButton("断开");
TitledBorder tb=new TitledBorder("");
ButtonGroup gb=new ButtonGroup();
public void init()//显示登录界面
{
jb1.addActionListener(this);
jb2.addActionListener(this);
jp1.add(jl1);
jp1.add(jtf1);
jp1.add(jrb1);
jp1.add(jrb2);
jp1.add(jrb3);
jp2.add(jl2);
jp2.add(jtf2);
jp2.add(jl3);
jp2.add(jtf3);
jp3.add(jb1);
jp3.add(jb2);
jp4.setLayout(new GridLayout(3,1));
jp4.add(jp1);
jp4.add(jp2);
jp4.add(jp3);
jf.add(jp4);
jtf2.setText("localhost");
jtf3.setText("6666");
gb.add(jrb1);
gb.add(jrb2);
gb.add(jrb3);
jf.setLocation(200, 200);
jf.setSize(350, 200);
jf.setResizable(false);
jf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
jf.setVisible(true);
}
public void actionPerformed(ActionEvent event)//事件触发
{
jb1.setText("连接");
jb2.setText("断开");
String s1=null;
if(event.getActionCommand().equals("断开"))
{
System.exit(0);
}
if(event.getActionCommand().equals("连接"))
{
if(jtf1.getText().equals(""))
{
JOptionPane.showMessageDialog(null,"请输入用户名!");
}
else if(!jrb1.isSelected()&&!jrb2.isSelected()&&!jrb3.isSelected())
{
JOptionPane.showMessageDialog(null,"请选择性别!");
}
else
{
jf.setVisible(false);
if(jrb1.isSelected())
{
s1="boy";
}
else if(jrb2.isSelected())
{
s1="girl";
}
else if(jrb3.isSelected())
{
s1="secret";
}
G_Menu gmu=new G_Menu();
gmu.getMenu(jtf1.getText(),s1);
gmu.sock();
}
}
}
}
public class Login
{
public static void main(String[] args)
{
new Landen().init();
}
}
主界面代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.net.*;
import java.io.*;
class G_Menu extends JFrame implements ActionListener
{
JFrame jf=new JFrame("聊天室");
public Socket_one soc;
public PrintWriter pw;
public JPanel jp1=new JPanel();
public JPanel jp2=new JPanel();
public JPanel jp3=new JPanel();
public JPanel jp4=new JPanel();
public JPanel jp5=new JPanel();
public JPanel jp6=new JPanel();
public JPanel jp7=new JPanel();
public static JTextArea jta1=new JTextArea(12,42);
public static JTextArea jta2=new JTextArea(12,42);
public JLabel jl1=new JLabel("对");
public static JComboBox jcomb=new JComboBox();
public JCheckBox jcb=new JCheckBox("私聊");
public JTextField jtf=new JTextField(36);
public JButton jb1=new JButton("发送>>");
public JButton jb2=new JButton("刷新");
public static DefaultListModel listModel1;
public static JList lst1;
public String na;
public String se;
public String message;
public void getMenu(String name,String sex)//显示聊天界面
{
jcomb.addItem("所有人");
this.na=name;
this.se=sex;
jta1.setEditable(false);
jta2.setEditable(false);
listModel1= new DefaultListModel();
lst1 = new JList(listModel1);
lst1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lst1.setVisibleRowCount(18);
lst1.setFixedCellHeight(28);
lst1.setFixedCellWidth(100);
JScrollPane jsp1=new JScrollPane(jta1);
JScrollPane jsp2=new JScrollPane(jta2);
JScrollPane jsp3=new JScrollPane(lst1);
jsp3.setBorder(new TitledBorder("好友列表"));
jsp1.setBorder(new TitledBorder("主聊天频道"));
jsp2.setBorder(new TitledBorder("我的频道"));
jp1.setLayout(new GridLayout(2,1));
jp1.add(jsp1);
jp1.add(jsp2);
jp2.setLayout(new FlowLayout(FlowLayout.LEFT));
jp2.add(jl1);
jp2.add(jcomb);
jp2.add(jcb);
jp3.setLayout(new FlowLayout(FlowLayout.LEFT));
jp3.add(jtf);
jp3.add(jb1);
jp4.setLayout(new GridLayout(2,1));
jp4.add(jp2);
jp4.add(jp3);
jp5.setLayout(new BorderLayout());
jp5.add(jp1,BorderLayout.NORTH);
jp5.add(jp4,BorderLayout.SOUTH);
jp6.setLayout(new BorderLayout());
jp6.add(jsp3,BorderLayout.NORTH);
jp6.add(jb2,BorderLayout.SOUTH);
jp7.setLayout(new FlowLayout(FlowLayout.LEFT));
jp7.add(jp5);
jp7.add(jp6);
jf.add(jp7);
jf.setLocation(200,200);
jf.setSize(700,650);
jf.setResizable(false);
jf.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
jf.setVisible(true);
jb1.addActionListener(this);
jb2.addActionListener(this);
jta1.setLineWrap(true);
jta2.setLineWrap(true);
jsp1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jsp1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jsp2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jsp2.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jsp3.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jsp3.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jf.pack();
}
public void sock()
{try{
String user=na+"("+se+")";//将用户信息保存成字符串形式
soc=new Socket_one(user);//创建客户端对象
pw=new PrintWriter(soc.socket.getOutputStream());//创建输出流
pw.println("1008611");//发送好友列表标识
pw.println(na+":"+se);//发送用户信息
pw.flush();
pw.println("10086");//发送进入聊天室标识
pw.println("【"+na+"】"+"进入聊天室");//发送进入聊天室信息
pw.flush();
}catch(Exception ex){
ex.printStackTrace();
}
}
public G_Menu() {//设置窗口关闭事件,如果点击窗口右上角叉号关闭,执行下边程序
jf.addWindowListener( new WindowAdapter(){
public void windowClosing(WindowEvent e){
try {
pw=new PrintWriter(soc.socket.getOutputStream());
pw.println("456987");//发送下线标识
pw.println(na+":离开聊天室");//发送下线信息
pw.flush();
jf.dispose();//关闭窗口
}catch(Exception ex) {
}
}
}
);
}
public void actionPerformed(ActionEvent event)//事件触发
{
jb1.setText("发送>>");
jb2.setText("刷新");
try{
pw=new PrintWriter(soc.socket.getOutputStream());
if(event.getActionCommand().equals("发送>>"))//点击发送触发
{
if(!jtf.getText().equals(""))
{
if(jcb.isSelected())
{
String name1=(String)jcomb.getSelectedItem();
message="悄悄话"+na+"("+se+")"+"对"+name1+"说:"+jtf.getText();
pw.println("841163574");//发送私聊标识
pw.println(na+":"+name1+"1072416535"+message);//发送私聊信息
pw.flush();
}
else{
pw.println("10010");//发送聊天标识
pw.println(na+"说:"+jtf.getText());//发送聊天信息
pw.flush();
}
}
}
else if(event.getActionCommand().equals("刷新"))//点击刷新触发
{
pw=new PrintWriter(soc.socket.getOutputStream());
pw.println("123654");//发送刷新标识
pw.flush();
}
}catch(Exception ex){
ex.printStackTrace();
}
jtf.setText("");//清空输入栏信息
jtf.requestFocus();//输入焦点
}
}
实体类代码:
import java.util.*;
import java.net.*;
import java.io.*;
class User
{
private String name;//用户姓名
private String sex;//用户性别
private Socket sock;//用户自己的socket
public User(String name,String sex,Socket sock)
{
setName(name);
setSex(sex);
setSock(sock);
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name=name;
}
public String getSex()
{
return sex;
}
public void setSex(String sex)
{
this.sex=sex;
}
public Socket getSock()
{
return sock;
}
public void setSock(Socket sock)
{
this.sock=sock;
}
}
使用说明:1、先将所有的类都编译一下
2、先运行服务器端代码
3、再运行登录界面代码