您的位置:首页 > 编程语言 > Java开发

java socket简易聊天室

2017-01-18 12:11 148 查看
对学完java socket的朋友有一定的帮助,因为当你学好这方面的知识后,想必也有做着玩玩的念头!如下:

项目图参照



User类

package hfz.addAction.cn;

//用户信息类
public class User{
private String name;

public User(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
/*
public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}*/
}


注册块



package hfz.Register.cn;

public class Register extends JFrame implements ActionListener{
JLabel labelName,labelName1;
JLabel labelSex,labelSex1;
JLabel labelPassword1,labelPassword11;
JLabel labelPassword2,labelPassword22;
ButtonGroup bg=new ButtonGroup();    //性别2个放一起选择
JTextField textName;
JRadioButton radioBoy;
JRadioButton radioGirl;
JLabel logoimagePosition1=new JLabel();
JLabel logoimagePosition2=new JLabel();

JPasswordField textPassword1;
JPasswordField textPassword2;

JButton b1;
JButton b2;
JButton b3;
JPanel Panel=new JPanel();
JLabel imagePos;

public Register()
{
this.setTitle(" 用户注册");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(530,300);

//窗口居中
Dimension us = this.getSize();
Dimension them = Toolkit.getDefaultToolkit().getScreenSize();
int X = (them.width - us.width) / 2 ;
int Y = (them.height - us.height) / 2 ;
this.setLocation(X,Y);
getContentPane().add(Panel);
Panel.setLayout(null);    //设置框架窗口的布局管理器为null

//添加组件
Font f = new Font("宋体",Font.PLAIN,12);
labelName = new JLabel("用户名:");
labelName.setFont(f);
labelName1 = new JLabel("(用户名长度限制为2-15字节)");
labelName1.setFont(f);
labelSex = new JLabel("性  别:");
labelSex.setFont(f);
labelSex1 = new JLabel("(请选择您的性别)");
labelSex1.setFont(f);
labelPassword1 = new JLabel("口  令:");
labelPassword1.setFont(f);
labelPassword11 = new JLabel("(密码不得少于6个字符多于12个字符)");
labelPassword11.setFont(f);
labelPassword2 = new JLabel("口  令:");
labelPassword2.setFont(f);
labelPassword22 = new JLabel("(请再输一遍确认)");
labelPassword22.setFont(f);
radioBoy = new JRadioButton("男 生");
radioBoy.setBackground(new Color(150,205,155));
radioBoy.setSelected(true);
bg.add(radioBoy);

radioGirl = new JRadioButton("女 生");
radioGirl.setBackground(new Color(150,205,155));
bg.add(radioGirl);

textName = new JTextField(10);
textName.setToolTipText("☆请输入您要注册的用户名☆");
textPassword1 = new JPasswordField(10);
textPassword1.setToolTipText("☆请输入您的密码☆");
textPassword2 = new JPasswordField(10);
textPassword2.setToolTipText("☆请再次输入密码确认☆");

b1 = new JButton("提   交");
b1.setBackground(new Color(0,155,0));
b1.addActionListener(this);
b2 = new JButton("重   置");
b2.setBackground(new Color(0,155,0));
b2.addActionListener(this);
b3 = new JButton("返   回");
b3.setBackground(new Color(0,155,0));
b3.addActionListener(this);
//背景
Icon image = new ImageIcon("image/2.jpg");
imagePos = new JLabel(image);

//手工设置各个组件的位置和大小
labelName.setBounds(new Rectangle(40, 20, 60, 20));
textName.setBounds(new Rectangle(100, 20, 180, 20));
labelName1.setBounds(new Rectangle(300, 20, 200, 20));
labelSex.setBounds(new Rectangle(40, 55, 60, 20));
radioBoy.setBounds(new Rectangle(95, 55, 55, 20));
logoimagePosition1.setBounds(new Rectangle(150, 52, 30, 25));
radioGirl.setBounds(new Rectangle(185, 55, 55, 20));
logoimagePosition2.setBounds(new Rectangle(245, 52, 30, 25));
labelSex1.setBounds(new Rectangle(300, 54, 150, 25));
labelPassword1.setBounds(new Rectangle(40, 85, 60, 20));
textPassword1.setBounds(new Rectangle(100, 85, 180, 20));
labelPassword11.setBounds(new Rectangle(300, 85, 220, 20));
labelPassword2.setBounds(new Rectangle(40, 120, 60, 20));
textPassword2.setBounds(new Rectangle(100, 120, 180, 20));
labelPassword22.setBounds(new Rectangle(300, 120, 220, 20));
b1.setBounds(new Rectangle(60, 210, 80, 25));
b2.setBounds(new Rectangle(170,210, 80, 25));
b3.setBounds(new Rectangle(280, 210, 80, 25));

imagePos.setBounds(new Rectangle(0,0,530,300));
//添加组件到面板
Panel.add(labelName);
Panel.add(textName);
Panel.add(labelName1);
Panel.add(labelSex);
Panel.add(radioBoy);
Panel.add(logoimagePosition1);
Panel.add(radioGirl);
Panel.add(logoimagePosition2);
Panel.add(labelSex1);
Panel.add(labelPassword1);
Panel.add(textPassword1);
Panel.add(labelPassword11);
Panel.add(labelPassword2);
Panel.add(textPassword2);
Panel.add(labelPassword22);
Panel.add(b1);
Panel.add(b2);
Panel.add(b3);

Panel.add(imagePos);
this.add(Panel);
this.setResizable(false);
this.setVisible(true);

}
@Override
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if(obj == b2){             //清空

textName.setText("");
textPassword1.setText("");
textPassword2.setText("");
}
if(obj==b3){               //返回

new ClientLogin();
this.setVisible(false);
}

if (obj==b1) {
Properties userPro=new Properties();
File file=new File("hfz.properties");
CatUtil.loadPro(userPro, file);
String u_name=textName.getText();
String u_pwd=new String(textPassword1.getPassword());
String u_pwd_ag=new String(
textPassword2.getPassword());
//判断是否存在
if (u_name.length()!=0) {
if (userPro.containsKey(u_name)) {
try {
throw new Exception("用户名存在");
} catch (Exception e1) {
e1.printStackTrace();
}
}else{
try {
isPassword(userPro, file, u_name, u_pwd, u_pwd_ag);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}else {
try {
throw new Exception("用户名不能为空");
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}

}

private void isPassword(Properties userPro,
File file, String u_name, String u_pwd, String u_pwd_ag) throws Exception {
if (u_pwd.equals(u_pwd_ag)) {
if (u_pwd.length() != 0) {
userPro.setProperty(u_name, u_pwd_ag);
try {
userPro.store(new FileOutputStream(file),
"Copyright (c) Boxcode Studio");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
b1.setEnabled(false);
//返回登陆界面
ClientLogin frame = new ClientLogin();
frame.setVisible(true);
setVisible(false);
} else {
throw new Exception("密码为空");
}
} else {
throw new Exception("密码不同");
}
}

}


相对应的登录块



package hfz.Login.cn;

public class ClientLogin extends JFrame implements ActionListener{
//窗口
private JLabel UserName;
private JLabel UserPwd;
private JPasswordField txtUserPwd;
public JTextField txtUserName;
private JButton Login;
private JButton Register;
private JButton Cancel;
private PrintWriter writer;
private BufferedReader reader;
JLabel imagePos;
public ClientLogin(){
this.setTitle("欢迎使用聊天室");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Font font=new Font("宋体",Font.PLAIN,12);
//组件
UserName=new JLabel("用户名:");
UserName.setFont(font);
UserPwd=new JLabel("密码:");
UserPwd.setFont(font);
txtUserPwd=new JPasswordField();
txtUserName=new JTextField();

Icon image = new ImageIcon("image/1.jpg");
imagePos = new JLabel(image);
//按钮
//设置按钮组件
Login=new JButton("登录");
Login.setFont(font);
Login.setBackground(new Color(0,155,0));
Login.setToolTipText("进入聊天界面  ");
Login.addActionListener(this);

Register=new JButton("注册");
Register.setFont(font);
Register.setBackground(new Color(0,155,0));
Register.setToolTipText(" 进入注册界面 ");
Register.addActionListener(this);

Cancel=new JButton("取消");
Cancel.setFont(font);
Cancel.setBackground(new Color(0,155,0));
Cancel.setToolTipText(" 清除内容 ") ;
Cancel.addActionListener(this);

//添加组件
JPanel panel=new JPanel();
getContentPane().add(panel);
panel.setLayout(null);
UserName.setBounds(new Rectangle(40, 20, 60, 20));//点击会出现矩形框
txtUserName.setBounds(new Rectangle(100, 20, 180, 20));
UserPwd.setBounds(new Rectangle(40, 60, 60, 20));
txtUserPwd.setBounds(new Rectangle(100, 60, 180, 20));

Login.setBounds(new Rectangle(40,100,60,20));
Register.setBounds(new Rectangle(130,100,60,20));
Cancel.setBounds(new Rectangle(220,
18578
100,60,20));

imagePos.setBounds(new Rectangle(0,0,320,160));

//把各组件加到框架窗口中
panel.add(UserName);
panel.add(UserPwd);
panel.add(txtUserName);
panel.add(txtUserPwd);
panel.add(Login);
panel.add(Register);
panel.add(Cancel);
panel.add(imagePos);
setResizable(false);
setSize(320,160);

Dimension us = this.getSize();
//获取屏幕的尺寸
Dimension them = Toolkit.getDefaultToolkit().getScreenSize();
int newX = (them.width - us.width) / 2 ;
int newY = (them.height - us.height) / 2 ;
this.setLocation(newX,newY);
setVisible(true);

}
//监听
@Override
public void actionPerformed(ActionEvent even){

JButton obj=(JButton)even.getSource();

if(obj==Cancel){               //取消

txtUserName.setText(null);
txtUserPwd.setText(null);
dispose();
}
else if (obj==Login){          //提交

String n=txtUserName.getText();
String p=String.valueOf(txtUserPwd.getPassword());

if(n.length()==0&&p.length()!=0){
JOptionPane.showMessageDialog(this,"您没有输入姓名","提示!",JOptionPane.CANCEL_OPTION);
return;
}
else if (n.length()!=0&&p.length()==0){
JOptionPane.showMessageDialog(this,"您没有输入密码","提示!",JOptionPane.CANCEL_OPTION);
return;
}
else if (n.length()==0&&p.length()==0){
JOptionPane.showMessageDialog(this,"您没有输入姓名和密码","提示!",JOptionPane.CANCEL_OPTION);
return;
}

//调用用户登陆方法
Properties userPro = new Properties();
File file = new File("hfz.properties");
CatUtil.loadPro(userPro, file);
String u_nameString=txtUserName.getText();
//System.out.println(nameString);
if (file.length()!=0) {
if (userPro.containsKey(u_nameString)) {
String u_pwd=new String(
txtUserPwd.getPassword());
if (u_pwd.equals(userPro.getProperty(u_nameString))) {

Login.setEnabled(false);
new Client(u_nameString);// 显示聊天界面
this.setVisible(false);
}else {
JOptionPane.showMessageDialog(null,"密码错误");
//重置
txtUserPwd.setText("");
txtUserName.requestFocus();
}
}else {
JOptionPane.showMessageDialog(null,"昵称不存在");
txtUserName.setText("");
txtUserPwd.setText("");
txtUserName.requestFocus();
}
}else {
JOptionPane.showMessageDialog(null,"昵称不存在");
txtUserName.setText("");
txtUserPwd.setText("");
txtUserName.requestFocus();
}

}
else if (obj==Register){       //注册

setVisible(false);
new hfz.Register.cn.Register();
}
}

}


客户端

package hfz.Clint.cn;

public class Client{

private JFrame frame;
private JList userList;
private JTextArea textArea;
private JTextField textField;
private JButton btn_start;
private JButton btn_stop;
private JButton btn_send;
private JButton setFont;   //字体面板
private JButton bColor;
private JPanel northPanel;
private JPanel southPanel;
private JScrollPane rightScroll;
private JScrollPane leftScroll;
private JSplitPane centerSplit;

private DefaultListModel listModel;
private boolean isConnected = false;

private Socket socket;
private PrintWriter writer;
private BufferedReader reader;
private MessageThread messageThread;// 负责接收消息的线程
private Map<String, User> onLineUsers = new HashMap<String, User>();// 所有在线用户

// 执行发送
public void send() {
if (!isConnected) {
JOptionPane.showMessageDialog(frame, "还没有连接服务器,无法发送消息!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message = textField.getText().trim();
if (message == null || message.equals("")) {
JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
sendMessage(frame.getTitle() + "@" + "ALL" + "@" + message);

textField.setText(null);
}

// 构造方法
public Client(final String username) {

Font f = new Font("宋体",Font.PLAIN,12);
textArea = new JTextArea();
textArea.setEditable(false);
textArea.setForeground(Color.red);
textField = new JTextField();
btn_start = new JButton("连接");
btn_stop = new JButton("断开");
btn_send = new JButton("发送");
setFont=new JButton("文字大小");
setFont.setToolTipText("☆点击选择字体☆");
setFont.addActionListener(new FontSet());
bColor=new JButton("字体颜色");
bColor.setToolTipText("☆选择颜色☆");
bColor.addActionListener(new setColor());
listModel = new DefaultListModel();
userList = new JList(listModel);

northPanel = new JPanel();
northPanel.setLayout(new GridLayout(1, 7));
northPanel.add(new JLabel("端口:8888"));
northPanel.add(new JLabel("服务器IP:localhost"));
northPanel.add(new JLabel("昵称:"+username));
northPanel.add(btn_start);
northPanel.add(btn_stop);
northPanel.setBorder(new TitledBorder("连接信息"));

rightScroll = new JScrollPane(textArea);
rightScroll.setBorder(new TitledBorder("消息显示区"));
leftScroll = new JScrollPane(userList);
leftScroll.setBorder(new TitledBorder("在线用户"));
southPanel = new JPanel(new BorderLayout());
southPanel.add(setFont,"North");
southPanel.add(bColor,"Center");
southPanel.add(textField,"South");
southPanel.add(btn_send, "East");
southPanel.setBorder(new TitledBorder("写消息"));

centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScroll,
rightScroll);
centerSplit.setDividerLocation(100);

frame = new JFrame("破产版聊天器");
// 更改JFrame的图标:
frame.setLayout(new BorderLayout());
frame.add(northPanel, "North");
frame.add(centerSplit, "Center");
frame.add(southPanel, "South");
frame.setSize(600, 400);
int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
frame.setLocation((screen_width - frame.getWidth()) / 2,
(screen_height - frame.getHeight()) / 2);
frame.setVisible(true);

// 写消息的文本框中按回车键时事件
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
send();
}
});

// 单击发送按钮时事件
btn_send.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send();
}
});

// 单击连接按钮时事件
btn_start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {

String name=username;
boolean flag = connectServer(name);
if (flag == false) {
try {
throw new Exception("与服务器连接失败!");
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
frame.setTitle(name);
JOptionPane.showMessageDialog(frame, "成功连接!");

}

});

// 单击断开按钮时事件
btn_stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!isConnected) {
JOptionPane.showMessageDialog(frame, "已处于断开状态,不要重复断开!",
"错误", JOptionPane.ERROR_MESSAGE);
return;
}
try {
boolean flag = closeConnection();// 断开连接
if (flag == false) {
throw new Exception("断开连接发生异常!");
}
JOptionPane.showMessageDialog(frame, "成功断开!");
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
}
}
});

// 关闭窗口时事件
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (isConnected) {
closeConnection();// 关闭连接
}
System.exit(0);// 退出程序
}
});
}

//颜色
class setColor implements ActionListener{
public void actionPerformed(ActionEvent e){
Object obj = e.getSource();
if(obj==(JButton)bColor){
Color ch = JColorChooser.showDialog(null,"Swing颜色选取器",getForeground());
if(ch != null){
textArea.setForeground(ch);
bColor.setBackground(ch);
}
}
}

private Color getForeground() {
// TODO Auto-generated method stub
return null;
}
}
//字体
class FontSet implements ActionListener{
public void actionPerformed(ActionEvent e){
Object obj = e.getSource();
if(obj== (JButton)setFont)
setFont();   //调用设置字体方法
}
}
public void setFont(){

FontChooser fChooser = new FontChooser(frame);
fChooser.setVisible(true);
Font myNewFont = fChooser.getSelectedFont();

textArea.setFont(myNewFont);
fChooser.dispose();
}

/**
* 连接服务器
*
* @param port
* @param hostIp
* @param u_nameString2
*/

public boolean connectServer(String name) {
// 连接服务器
try {
socket = new Socket("localhost",8888);// 根据端口号和服务器ip建立连接
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket
.getInputStream()));

// 发送客户端用户基本信息(用户名和ip地址)
sendMessage(name);
// 开启接收消息的线程
messageThread = new MessageThread(reader, textArea);
messageThread.start();
isConnected = true;// 已经连接上了
return true;
} catch (Exception e) {
textArea.append("连接失败"+"\r\n");
isConnected = false;// 未连接上
return false;
}
}

/**
* 发送消息
*
* @param message
*/
public void sendMessage(String message) {
writer.println(message);
writer.flush();
}

/**
* 客户端主动关闭连接
*/
@SuppressWarnings("deprecation")
public synchronized boolean closeConnection() {
try {
sendMessage("CLOSE");// 发送断开连接命令给服务器
messageThread.stop();// 停止接受消息线程
// 释放资源
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
if (socket != null) {
socket.close();
}
isConnected = false;
return true;
} catch (IOException e1) {
e1.printStackTrace();
isConnected = true;
return false;
}
}

// 不断接收消息的线程
class MessageThread extends Thread {
private BufferedReader reader;
private JTextArea textArea;

// 接收消息线程的构造方法
public MessageThread(BufferedReader reader, JTextArea textArea) {
this.reader = reader;
this.textArea = textArea;
}

// 被动的关闭连接
public synchronized void closeCon() throws Exception {
// 清空用户列表
listModel.removeAllElements();
// 被动的关闭连接释放资源
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
if (socket != null) {
socket.close();
}
isConnected = false;// 修改状态为断开
}

public void run() {
String message = "";
while (true) {
try {
message = reader.readLine();
StringTokenizer stringTokenizer = new StringTokenizer(
message, "/@");
String command = stringTokenizer.nextToken();// 命令
if (command.equals("CLOSE"))// 服务器已关闭命令
{
textArea.append("服务器已关闭!\r\n");
closeCon();// 被动的关闭连接
return;// 结束线程
} else if (command.equals("ADD")) {// 有用户上线更新在线列表
String username = "";
//String userIp = "";
if ((username = stringTokenizer.nextToken()) != null) {
User user = new User(username);
onLineUsers.put(username, user);
listModel.addElement(username);
}
} else if (command.equals("DELETE")) {// 有用户下线更新在线列表
String username = stringTokenizer.nextToken();
User user = (User) onLineUsers.get(username);
onLineUsers.remove(user);
listModel.removeElement(username);
} else if (command.equals("USERLIST")) {// 加载在线用户列表
int size = Integer
.parseInt(stringTokenizer.nextToken());
String username = null;
// String userIp = null;
for (int i = 0; i < size; i++) {
username = stringTokenizer.nextToken();
//   userIp = stringTokenizer.nextToken();
User user = new User(username);
onLineUsers.put(username, user);
listModel.addElement(username);
}
} else if (command.equals("MAX")) {// 人数已达上限
textArea.append(stringTokenizer.nextToken()
+ stringTokenizer.nextToken() + "\r\n");
closeCon();// 被动的关闭连接
JOptionPane.showMessageDialog(frame, "服务器缓冲区已满!", "错误",
JOptionPane.ERROR_MESSAGE);
return;// 结束线程
} else {// 普通消息
textArea.append(message + "\r\n");
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}


服务端

package hfz.Server.cn;

public class Server {

private JFrame frame;
private JTextArea contentArea;
private JTextField txt_max;
//private JTextField txt_port;
private JButton btn_start;
private JButton btn_stop;
private JPanel northPanel;
private JScrollPane rightPanel;
private JScrollPane leftPanel;
private JSplitPane centerSplit;
private JList userList;
private DefaultListModel listModel;

private ServerSocket serverSocket;
private ServerThread serverThread;
private ArrayList<ClientThread> clients;

private boolean isStart = false;

// 主方法,程序执行入口
public static void main(String[] args) {
new Server();
}

// 构造放法
public Server() {
frame = new JFrame("终端显示");
contentArea = new JTextArea();
contentArea.setEditable(false);
contentArea.setForeground(Color.blue);
txt_max = new JTextField("10");
//txt_port = new JTextField("8888");
btn_start = new JButton("启动");
btn_stop = new JButton("停止");
btn_stop.setEnabled(false);
listModel = new DefaultListModel();
userList = new JList(listModel);

leftPanel = new JScrollPane(userList);
leftPanel.setBorder(new TitledBorder("在线用户"));

rightPanel = new JScrollPane(contentArea);
rightPanel.setBorder(new TitledBorder("消息显示"));

centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel,
rightPanel);
centerSplit.setDividerLocation(100);
northPanel = new JPanel();
northPanel.setLayout(new GridLayout(1, 6));
northPanel.add(new JLabel("人数上限"));
northPanel.add(txt_max);
northPanel.add(new JLabel("端口:8888"));
//northPanel.add(txt_port);
northPanel.add(btn_start);
northPanel.add(btn_stop);
northPanel.setBorder(new TitledBorder("配置信息"));

frame.setLayout(new BorderLayout());
frame.add(northPanel, "North");
frame.add(centerSplit, "Center");
frame.setSize(400, 200);
//frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());//设置全屏
int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
frame.setLocation((screen_width - frame.getWidth()) / 2,
(screen_height - frame.getHeight()) / 2);
frame.setVisible(true);

// 关闭窗口时事件
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (isStart) {
closeServer();// 关闭服务器
}
System.exit(0);// 退出程序
}
});

// 单击启动服务器按钮时事件
btn_start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isStart) {
JOptionPane.showMessageDialog(frame, "服务器已处于启动状态,不要重复启动!",
"错误", JOptionPane.ERROR_MESSAGE);
return;
}
int max;
//int port;

try {
try {
max = Integer.parseInt(txt_max.getText());
} catch (Exception e1) {
throw new Exception("人数上限为正整数!");
}
if (max <= 0) {
throw new Exception("人数上限为正整数!");
}

serverStart(max);
contentArea.append("服务器已成功启动!人数上限:" + max + "\r\n");
JOptionPane.showMessageDialog(frame, "服务器成功启动!");
btn_start.setEnabled(false);
txt_max.setEnabled(false);
// txt_port.setEnabled(false);
btn_stop.setEnabled(true);
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
}
}
});

// 单击停止服务器按钮时事件
btn_stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!isStart) {
JOptionPane.showMessageDialog(frame, "服务器还未启动,无需停止!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
try {
closeServer();
btn_start.setEnabled(true);
txt_max.setEnabled(true);
// txt_port.setEnabled(true);
btn_stop.setEnabled(false);
contentArea.append("服务器成功停止!\r\n");
JOptionPane.showMessageDialog(frame, "服务器成功停止!");
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, "停止服务器发生异常!", "错误",
JOptionPane.ERROR_MESSAGE);
}
}
});
}

// 启动服务器
public void serverStart(int max) throws java.net.BindException {
try {
clients = new ArrayList<ClientThread>();
serverSocket = new ServerSocket(8888);
serverThread = new ServerThread(serverSocket,max);
serverThread.start();
isStart = true;
} catch (BindException e) {
isStart = false;
//throw new BindException("端口号已被占用,请换一个!");
} catch (Exception e1) {
e1.printStackTrace();
isStart = false;
throw new BindException("启动服务器异常!");
}
}

// 关闭服务器
@SuppressWarnings("deprecation")
public void closeServer() {
try {
if (serverThread != null)
serverThread.stop();// 停止服务器线程

for (int i = clients.size() - 1; i >= 0; i--) {
// 给所有在线用户发送关闭命令
clients.get(i).getWriter().println("CLOSE");
clients.get(i).getWriter().flush();
// 释放资源
clients.get(i).stop();// 停止此条为客户端服务的线程
clients.get(i).reader.close();
clients.get(i).writer.close();
clients.get(i).socket.close();
clients.remove(i);
}
if (serverSocket != null) {
serverSocket.close();// 关闭服务器端连接
}
listModel.removeAllElements();// 清空用户列表
isStart = false;
} catch (IOException e) {
e.printStackTrace();
isStart = true;
}
}

// 群发服务器消息
public void sendServerMessage(String message) {
for (int i = clients.size() - 1; i >= 0; i--) {
clients.get(i).getWriter().println("服务器:" + message + "(多人发送)");
clients.get(i).getWriter().flush();
}
}

// 服务器线程
class ServerThread extends Thread {
private ServerSocket serverSocket;
private int max;// 人数上限

// 服务器线程的构造方法
public ServerThread(ServerSocket serverSocket,int max) {
this.serverSocket = serverSocket;
this.max = max;
}

public void run() {
while (true) {// 不停的等待客户端的链接
try {
Socket socket = serverSocket.accept();
if (clients.size() == max) {// 如果已达人数上限
BufferedReader r = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter w = new PrintWriter(socket
.getOutputStream());
// 接收客户端的基本用户信息
String inf = r.readLine();
StringTokenizer st = new StringTokenizer(inf, "@");
User user = new User(st.nextToken());
// 反馈连接成功信息
w.println("MAX@服务器:对不起," + user.getName()
+  ",服务器在线人数已达上限,请稍后尝试连接!");
w.flush();
// 释放资源
r.close();
w.close();
socket.close();
continue;
}
ClientThread client = new ClientThread(socket);
client.start();// 开启对此客户端服务的线程
clients.add(client);
listModel.addElement(client.getUser().getName());// 更新在线列表
contentArea.append(client.getUser().getName()
+  "上线!\r\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

// 为一个客户端服务的线程
class ClientThread extends Thread {
private Socket socket;
private BufferedReader reader;
private PrintWriter writer;
private User user;

public BufferedReader getReader() {
return reader;
}

public PrintWriter getWriter() {
return writer;
}

public User getUser() {
return user;
}

// 客户端线程的构造方法
public ClientThread(Socket socket) {
try {
this.socket = socket;
reader = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
writer = new PrintWriter(socket.getOutputStream());
// 接收客户端的基本用户信息
String inf = reader.readLine();
StringTokenizer st = new StringTokenizer(inf, "@");
user = new User(st.nextToken());
// 反馈连接成功信息
writer.println(user.getName() +  "与服务器连接成功!");
writer.flush();
// 反馈当前在线用户信息
if (clients.size() > 0) {
String temp = "";
for (int i = clients.size() - 1; i >= 0; i--) {
temp += (clients.get(i).getUser().getName() + "/" )
+ "@";
}
writer.println("USERLIST@" + clients.size() + "@" + temp);
writer.flush();
}
// 向所有在线用户发送该用户上线命令
for (int i = clients.size() - 1; i >= 0; i--) {
clients.get(i).getWriter().println(
"ADD@" + user.getName());
clients.get(i).getWriter().flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}

@SuppressWarnings("deprecation")
public void run() {// 不断接收客户端的消息,进行处理。
String message = null;
while (true) {
try {
message = reader.readLine();// 接收客户端消息
if (message.equals("CLOSE"))// 下线命令
{
contentArea.append(this.getUser().getName()
+  "下线!\r\n");
// 断开连接释放资源
reader.close();
writer.close();
socket.close();

// 向所有在线用户发送该用户的下线命令
for (int i = clients.size() - 1; i >= 0; i--) {
clients.get(i).getWriter().println(
"DELETE@" + user.getName());
clients.get(i).getWriter().flush();
}

listModel.removeElement(user.getName());// 更新在线列表

// 删除此条客户端服务线程
for (int i = clients.size() - 1; i >= 0; i--) {
if (clients.get(i).getUser() == user) {
ClientThread temp = clients.get(i);
clients.remove(i);// 删除此用户的服务线程
temp.stop();// 停止这条服务线程
return;
}
}
} else {
dispatcherMessage(message);// 转发消息
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

// 转发消息
public void dispatcherMessage(String message) {
StringTokenizer stringTokenizer = new StringTokenizer(message, "@");
String source = stringTokenizer.nextToken();
String owner = stringTokenizer.nextToken();
String content = stringTokenizer.nextToken();
message = source + "说:" + content;
contentArea.append(message + "\r\n");
if (owner.equals("ALL")) {// 群发
for (int i = clients.size() - 1; i >= 0; i--) {
clients.get(i).getWriter().println(message);
clients.get(i).getWriter().flush();
}
}
}
}
}


主类:先开启服务,再登录连接

package hfz.main.cn;

import hfz.Login.cn.ClientLogin;

public class Test {

public static void main(String[] args) {
new ClientLogin().txtUserName.getText();
}

}




代码资源地址补上,也感谢支持:

javaSocket简单聊天室
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  socket java 聊天