//服务端
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import Layout.Server.Client;
/**
*
* @author 晓晓
*
*/
public class Server {
private JFrame frame; //创建一个swing界面
// private JList<String> clientlist; //用户列表
private JTextArea textArea; //输入消息的文本域
public JTextArea getTextArea() {
return textArea;
}
public void setTextArea(JTextArea textArea) {
this.textArea = textArea;
}
private JTextField inputbox; //输入框
private JTextField inputbox_max_people; //人数上限输入框
private JTextField inputbox_port=null; //接口输入框
// private JTextField textField_send;
private JTextField inputbox_kickeduser; //被踢用户输入框
private JButton btn_start; //启动按钮
private JButton btn_pause; //暂停按钮
private JButton btn_send; //消息发送按钮
private JButton btn_kickuser; //踢出用户按钮
private JPanel southPanel; //上方(北)界面
private JPanel northPanel; //下方(南)界面
private JScrollPane leftscrollPanel; //显示在线人员的左方滚动面板
private JScrollPane rightscrollPanel; //显示消息的右方滚动面板
//分割面板
private JSplitPane centerSplit;
private DefaultListModel<String> listModel; //列表模型
private JPanel kickeduser;
private JLabel kick_user;
private JLabel to_be_continued;
// private ServerSocket server;
// private ServerThread ServerThread;
private boolean isStart = false;//定义一个布尔类的服务器启动标记
int port;//设置服务器端口
int max_people;//设置人数上限
static ArrayList<Client> socket_xc = new ArrayList<Client>();
ServerSocket ss = null; //服务器
private JList Clientlist;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Server window = new Server();
window.frame.setVisible(true);
window.frame.addWindowListener(new WindowAdapter() {
//增加一个监听器,遍历用户列表,将此服务器下线广播到每一个用户
@Override
public void windowClosing(WindowEvent arg0) {
for(Client client:socket_xc) {
String send_massage = "WARNING@"+"服务器已下线"; //窗口提示
try {
//字节输出流
OutputStream out = client.socket.getOutputStream();//返回此套接字的输出流。
PrintWriter write = new PrintWriter(out);
write.println(send_massage);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
});
}catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Server() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
textArea = new JTextArea();
textArea.setEditable(false);
Clientlist = new JList();
// Clientlist.setFocusable(false);
//连接信息区域的框体
inputbox = new JTextField();
inputbox_max_people = new JTextField();
inputbox_max_people.setSize(58, 26);
inputbox_max_people.setLocation(96, 29);
inputbox_port = new JTextField("8080");
inputbox_port.setSize(128, 28);
inputbox_port.setLocation(420, 27);
btn_start = new JButton("启动");
btn_start.setSize(119, 33);
btn_start.setLocation(561, 25);
btn_start.addActionListener(new ActionListener() {
//增加一个启动的监听器
public void actionPerformed(ActionEvent arg0) {
start();
}
});
btn_pause = new JButton("暂停");
btn_pause.setSize(112, 34);
btn_pause.setLocation(684, 25);
btn_pause.addActionListener(new ActionListener() {
//增加一个暂停的监听器
@Override
public void actionPerformed(ActionEvent e) {
pause();
}
});
btn_send = new JButton("发送");
btn_send.addActionListener(new ActionListener() {
//增加一个发送的监听器
public void actionPerformed(ActionEvent arg0) {
send();
}
});
//用户列表获取
listModel = new DefaultListModel<String>();
JList<String> list = new JList<String>(listModel);
// list = new JList<String>(listModel);
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent arg0) {
// TODO Auto-generated method stub
if (!arg0.getValueIsAdjusting()) {
// 获取所有被选中的选项索引
int index = list.getSelectedIndex();
if (index >= 0) {
String select_Name = listModel.getElementAt(index);
inputbox_kickeduser.setText(select_Name); // 根据下标获取被踢用户名字
}
}
}
});
//连接信息部分的界面
northPanel = new JPanel();
northPanel.setLayout(null);
northPanel.setBorder(new TitledBorder("连接信息"));//设置标题Title
JLabel people_line = new JLabel("人数上限:");
people_line.setSize(80, 22);
people_line.setLocation(14, 33);
northPanel.add(people_line);
northPanel.add(inputbox_max_people);
northPanel.setBounds(0, 0, 809, 64);
JLabel port_port = new JLabel("端口:");
port_port.setSize(58, 28);
port_port.setLocation(358, 28);
northPanel.add(port_port);
northPanel.add(inputbox_port);
northPanel.add(btn_start);
northPanel.add(btn_pause);
//中间的滚动面板部分
//左边在线用户面板部分
leftscrollPanel = new JScrollPane(list);
leftscrollPanel.setBorder(new TitledBorder("在线用户"));
//右边消息显示区面板部分
rightscrollPanel = new JScrollPane(textArea);
rightscrollPanel.setBorder(new TitledBorder("消息显示区"));
//分割中间部分面板
centerSplit =new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftscrollPanel,rightscrollPanel);
centerSplit.setSize(809, 314);
centerSplit.setLocation(0, 72);
centerSplit.setDividerLocation(100); //设置分割的位置为从左向右100
//底部(南)面板界面
southPanel = new JPanel(new BorderLayout());
southPanel.setSize(811, 64);
southPanel.setLocation(0, 387);
southPanel.setBorder(new TitledBorder("写信息"));
southPanel.add(inputbox,"Center"); //信息输入位置
southPanel.add(btn_send,"East"); //发送按钮
frame = new JFrame("服务端");
frame.getContentPane().setLayout(null);
frame.getContentPane().add(northPanel,"North");
frame.getContentPane().add(centerSplit,"Center");
frame.getContentPane().add(southPanel,"South");
//服务器功能操作界面
kickeduser = new JPanel();
kickeduser.setBounds(810, 0, 192, 438);
frame.getContentPane().add(kickeduser);
kickeduser.setLayout(null);
kick_user = new JLabel("被踢用户");
kick_user.setSize(75, 26);
kick_user.setLocation(2, 29);
kickeduser.add(kick_user);
inputbox_kickeduser = new JTextField();
inputbox_kickeduser.setSize(80, 25);
inputbox_kickeduser.setLocation(66, 30);
kickeduser.add(inputbox_kickeduser);
inputbox_kickeduser.setColumns(10);
btn_kickuser = new JButton("踢");
btn_kickuser.setSize(47, 26);
btn_kickuser.setLocation(145, 29);
btn_kickuser.addActionListener(new ActionListener() {
//增加一个踢人的监听
@Override
public void actionPerformed(ActionEvent e) {
Kick();
}
});
kickeduser.add(btn_kickuser);
to_be_continued = new JLabel("未完待续...");
to_be_continued.setSize(118, 26);
to_be_continued.setLocation(34, 219);
kickeduser.add(to_be_continued);
frame.setSize(1020,498);
int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
frame.setLocation((screen_width-frame.getWidth())/2,(screen_height-frame.getWidth())/2);
frame.setVisible(true); //设置可见
}
//客户发给服务器的消息
public class Client extends Thread{
private Socket socket = null;
private InputStream in = null;
private BufferedReader buf = null;
private PrintWriter write =null;
private OutputStream out = null;
public Client() {
}
public Client(String name,Socket socket) {
super(name);
this.socket = socket;
}
@Override
public void run() {
try {
in = socket.getInputStream();//返回输入流。
buf = new BufferedReader(new InputStreamReader(in));
while(true) {
if(this.isInterrupted()) {
//throw new InterruptedException();
return;
}
String info_accept = buf.readLine();
System.out.println(info_accept);
// StringTokenizer(String str, String delim)
// 构造一个用来解析 str 的 StringTokenizer 对象,并提供一个指定的分隔符。
StringTokenizer str = new StringTokenizer(info_accept,"@");//分割接收的信息,提取命令
String order = str.nextToken();//命令
String send_massage = str.nextToken();
//区分消息种类
switch(order) {
case "SEND_MESSAGE":
//私聊
if(send_massage.equals(" ")) {
System.out.println("加入私聊");
//私聊用户的名字
String select_Name = str.nextToken();
//私聊内容
send_massage = str.nextToken();
//列遍每一个用户找到私聊用户和自己
for(Client client:socket_xc) {
//找到私聊的用户
if(client.getName().equals(select_Name)) {
String info_send = " "+"@"+this.getName()+":"+send_massage+"( 对"+select_Name+"私聊)";
out = client.socket.getOutputStream(); //返回此套接字的输出流。
write = new PrintWriter(out);
write.println(info_send);//将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
textArea.append(this.getName()+":"+send_massage+"( 对"+select_Name+"私聊)"+"\n");break;//将接收的消息打印到服务器的消息显示区
}
//找到自己
if(client == this) {
String info_send = " "+"@"+this.getName()+":"+send_massage+"( 对"+select_Name+"私聊)";
out = client.socket.getOutputStream();//返回此套接字的输出流。
write = new PrintWriter(out);
write.println(info_send);//将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
textArea.append(info_send);break;
}
}
}else {
for(Client client:socket_xc) {//列遍每一个用户,将接收到的东西发送给他们
String info_send = "SEND_MESSAGE@"+this.getName()+":"+send_massage;
out = client.socket.getOutputStream();//返回此套接字的输出流。
write = new PrintWriter(out);
write.println(info_send);//将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
}
textArea.append(this.getName()+":"+send_massage+"\n");//将接收的消息打印到服务器的消息显示区
}
break;
case "OFFLINE":
for(Client client:socket_xc) {//列遍每一个用户,将此用户下线信息广播出去
if(client != this) {
String info_send = "OFFLINE@"+this.getName();
out = client.socket.getOutputStream();//返回此套接字的输出流。
write = new PrintWriter(out);
write.println(info_send);//将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
}
}
listModel.removeElement(this.getName());//刷新服务器在线列表
textArea.append("服务器:"+this.getName()+"已下线!\n");
this.interrupt();
//用迭代器遍历
Iterator<Client> clients = socket_xc.iterator();
while(clients.hasNext()) {//列遍每一个用户,删除下线用户
Client client = clients.next();
if(client == this) {
clients.remove();
}
}
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//服务器发给客户端
public class Accept extends Thread {
private ServerSocket ss;
private InputStream in = null;
private BufferedReader buf = null;
private OutputStream out =null;
private PrintWriter write = null;
public Accept() {
}
public Accept(String name) {
super(name);
}
public Accept(ServerSocket ss) {
this.ss = ss;
}
@Override
public void run() {
// Socket socket = null;
if(isStart) {
while(true) {
try {
Socket socket = ss.accept();//接收客户端的连接
if(socket_xc.size()<max_people) {
in = socket.getInputStream();//返回此套接字的输入流。
buf = new BufferedReader(new InputStreamReader(in));
String name = buf.readLine();//接收用户信息
StringTokenizer str = new StringTokenizer(name,"@");//分割接收的信息,提取命令
//登陆提示
if(str.nextToken().equals("ONLINE")) {
name = str.nextToken();//获得客户名字
Client newclient = new Client(name,socket);//创建一个客户端线程
newclient.start();//启动客户端线程
socket_xc.add(newclient);//保存客户端线程
textArea.append("服务器:欢迎用户"+newclient.getName()+"上线!\n");
listModel.addElement(newclient.getName());
}
//将新用户上线信息广播到其它用户
for(Client client_:socket_xc) {
//if(client_.isInterrupted()) continue;//排除已经中断的客户线程(中断的线程还存在)
out = client_.socket.getOutputStream();//返回此套接字的输出流。
write = new PrintWriter(out);
String info_send ="SEND_MESSAGE@服务器:欢迎用户"+name+"上线";
write.println(info_send);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
String info_send_2 ="NEWCLIENT@"+name;
write.println(info_send_2);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
}
//将其它在线用户的名字信息广播到新用户
for(Client client_:socket_xc) {
if(client_.socket != socket) {
out = socket.getOutputStream();//返回此套接字的输出流。
write = new PrintWriter(out);
String info_send ="NEWCLIENT@"+client_.getName();
System.out.println("在线用户消息:"+info_send);
write.println(info_send);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
}
}
}else {
OutputStream out = socket.getOutputStream();//返回此套接字的输出流。
PrintWriter w = new PrintWriter(out);
String info_send ="WARNING@"+"登陆服务器失败,服务器登陆人数已达上限";//提示
w.println(info_send);将信息写进字符缓冲区
w.flush();//刷新该流的缓冲
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public void start() {
try {
if(isStart){//服务器已经启动
JOptionPane.showMessageDialog(null,"服务器("+port+"端口)已启动!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
return;
}
//判断连接信息输入合法性
String max_peo = inputbox_max_people.getText();
if(max_peo.equalsIgnoreCase("")) {//判断上限人数是否为空
JOptionPane.showMessageDialog(null,"请输入有效人数上限!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
return;
}
max_people = Integer.parseInt(max_peo);//获取输入的人数上限
if(inputbox_port.getText().length() == 0) {//判断是否设置端口
JOptionPane.showMessageDialog(null,"请输入有效端口!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
return;
}
port=Integer.parseInt(inputbox_port.getText());//获取输入的服务器端口号
//启动服务器
ss = new ServerSocket(port);
isStart = true;
//在消息区显示已经启动
textArea.append("服务器:服务器("+port+"端口)已启动!人数上限:"+max_people+"\n");
inputbox_port.setEditable(false);//设置端口文本域不可编辑
inputbox_max_people.setEditable(false);//设置人数上限文本域不可编辑
// btn_start.setEnabled(false);
JOptionPane.showMessageDialog(null,"服务器("+port+"端口)启动成功!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
Accept accept = new Accept(ss);//初始化接收客户端的线程
accept.start();//启动等待客户端线程
// ServerThread st= new ServerThread(server);
}catch (IOException e) {
JOptionPane.showMessageDialog(null,"服务器启动失败!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
e.printStackTrace();
}
}
private void pause() {
try {
if(!isStart) {
JOptionPane.showMessageDialog(null,"服务器未启动!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
return;
}
inputbox_port.setEditable(true);//将端口设置为可以编辑
inputbox_max_people.setEditable(true);//设置人数上限文本域可编辑
listModel.clear();//删除在线用户列表中的所有元素
for(Client client:socket_xc) {//这里的格式不懂为什么for循环里面这样写
//列遍每一个用户线程发送服务器下线通知,并将其线程中断
String info_send = "WARNING@"+"服务器已下线";
OutputStream out = client.socket.getOutputStream();//返回此套接字的输出流。
PrintWriter write = new PrintWriter(out);
write.println(info_send);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
client.socket.close();
client.interrupt();
}
ss.close();
textArea.append("服务器:("+port+"端口)已关闭!\n");
isStart = false;
//关闭所有相关资源(未实现)(线程,在线用户集合)
JOptionPane.showMessageDialog(null,"服务器("+port+"端口)已关闭!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
}catch (IOException e1) {
JOptionPane.showMessageDialog(null,"服务器关闭失败!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
e1.printStackTrace();
}
}
private void send() {
try {
if(!isStart) {
JOptionPane.showMessageDialog(null,"请先启动服务器", "系统信息", JOptionPane.INFORMATION_MESSAGE);
return;
}
/*
* 定义发信息的输出流
*/
OutputStream out= null;
PrintWriter write = null;
//发送信息到各个客户端
String info = inputbox.getText();
inputbox.setText("");//将消息框置为空
if(info.equals("")) {
JOptionPane.showMessageDialog(null,"发送的内容为空", "服务器", JOptionPane.INFORMATION_MESSAGE);
return;
}
textArea.append("服务器:"+info+"\n");
String info_send = "SEND_MESSAGE@服务器:"+info;
for(Client client:socket_xc) {//列 遍每一个用户,将接收到的东西发送给他们
out = client.socket.getOutputStream();//返回此套接字的输出流。
write = new PrintWriter(out);
write.println(info_send);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
}
}catch (IOException e) {
JOptionPane.showMessageDialog(null,"发送消息失败", "服务器", JOptionPane.INFORMATION_MESSAGE);
e.printStackTrace();
}
}
private void Kick() {
String kickeduser_Name = inputbox_kickeduser.getText();
if(!kickeduser_Name.equals("")) {
listModel.removeElement(kickeduser_Name);//从在线列表中踢出
OutputStream out;
PrintWriter write;
try {
for(Client client:socket_xc) {
if(client.getName().equals(kickeduser_Name)) {
String clientName = "Kick"+"@"+client.getName();
out = client.socket.getOutputStream();
write = new PrintWriter(out);
write.println(clientName);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
socket_xc.remove(client);
client.interrupt();
textArea.append("服务器:"+kickeduser_Name+"已被踢出群聊\n");
JOptionPane.showMessageDialog(null,kickeduser_Name+"已被踢出群聊", "服务器", JOptionPane.INFORMATION_MESSAGE);
}else {
String kickeduserName = "OFFLINE@"+kickeduser_Name;
out = client.socket.getOutputStream();
write = new PrintWriter(out);
write.println(kickeduserName);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
}
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}//返回此套接字的输出流。
}else {
JOptionPane.showMessageDialog(null,"请输入或选择被踢用户!", "服务器", JOptionPane.INFORMATION_MESSAGE);
}
}
}
//客户端
package Practical_Training1;
/**
* 客户端
* @author 晓晓
*
*/
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import Layout.Client;
import Practical_Training.Client.Accept_info;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UncheckedIOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
public class ClientSide extends JFrame{
private JFrame frame; //创建一个swing界面
// private JList<String> clientlist; //用户列表
private JTextArea textArea; //文本域
private JTextField inputbox; //输入框
private JTextField inputbox_port; //接口输入框
private JTextField inputbox_ip; //ip输入框
private JTextField inputbox_username; //用户名输入框
private JButton btn_connect; //连接按钮
private JButton btn_disconnect; //断开连接按钮
private JButton btn_send; //消息发送按钮
private JPanel southPanel; //上方(北)界面
private JPanel northPanel; //下方(南)界面
private JScrollPane leftscrollPanel; //显示在线人员的左方滚动面板
private JScrollPane rightscrollPanel; //显示消息的右方滚动面板
private JSplitPane centerSplit; //分割面板
private DefaultListModel<String> listModel; //列表模型
static ArrayList<Client> socket_xc = new ArrayList<Client>();
private int port;//服务器的端口
Accept accept;
private String ip;//服务器地址
private String name;//客户姓名
private OutputStream out ; //客户端输出流
private InputStream in = null;//客户端输入流
private PrintWriter write ;//用来创建一个文件并向文本文件写入数据
private BufferedReader buf = null;//字符流
boolean isConnect = false;//判断是否连接服务器的标识
// 构造方法
public ClientSide() {
textArea = new JTextArea();
textArea.setEditable(false);//将消息显示区设为不可编辑
//连接信息区域的框体
inputbox = new JTextField();
inputbox_username = new JTextField("xiaoxiao");
inputbox_username.setSize(86, 24);
inputbox_username.setLocation(60, 26);
inputbox_ip = new JTextField("127.0.0.1");
inputbox_ip.setSize(86, 24);
inputbox_ip.setLocation(295, 26);
inputbox_port = new JTextField("8080");
inputbox_port.setSize(86, 24);
inputbox_port.setLocation(455, 26);
btn_connect = new JButton("连接");
btn_connect.setSize(113, 27);
btn_connect.setLocation(567, 25);
btn_connect.addActionListener(new ActionListener() {
//添加一个连接的监听器
@Override
public void actionPerformed(ActionEvent e) {
try {
if(isConnect) {
return;
}
String Local_IP=InetAddress.getLocalHost().getHostAddress();//获取本机地址
// 依次判断是否输入name,ip,port
//name
if(inputbox_username.getText().equals("")) {
JOptionPane.showMessageDialog(null,"未输入用户名!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
//showMessageDialog的用法见https://www.cnblogs.com/guohaoyu110/p/6440333.html
return;
}
name = inputbox_username.getText();//获取输入的客户姓名
String username = "ONLINE@"+name+"@"+Local_IP;
// 解决用户名重复依旧可以登录的问题
// for(Client client:socket_xc) {
// if(client.getName().equals(inputbox_username.getText())) {
// JOptionPane.showMessageDialog(null,"用户名已存在!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
// }
// }
// Iterator<Client> clients = socket_xc.iterator();
// while(clients.hasNext()) {//列遍每一个用户
// Client client = clients.next();
// String old_name = client.getName();
// if(inputbox_username.getText().equals(old_name)) {
// JOptionPane.showMessageDialog(null,"用户名已存在!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
// }
// }
//ip
if(inputbox_ip.getText().equalsIgnoreCase("")) {
//判断是否输入IP地址
JOptionPane.showMessageDialog(null,"未输入服务器IP!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
return;
}
ip = inputbox_ip.getText();//获取输入的ip地址
//port
if(inputbox_port.getText().equals("")) {
//判断是否输入端口号
JOptionPane.showMessageDialog(null,"未输入服务器端口号!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
return;
}
port = Integer.parseInt(inputbox_port.getText());//获取输入的服务器端口号
//连接服务器
Socket socket = new Socket(ip,port);
textArea.append("服务器连接成功!\n");
JOptionPane.showMessageDialog(null,"连接服务器成功!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
//将port、ip、name设为不可编辑
inputbox_ip.setEditable(false);
inputbox_port.setEditable(false);
inputbox_username.setEditable(false);
isConnect=true;
accept = new Accept(socket);
accept.start();
out = socket.getOutputStream();//返回此套接字的输出流。
write = new PrintWriter(out);
write.println(username);//将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
} catch (UncheckedIOException e1) {
JOptionPane.showMessageDialog(null,"连接服务器失败,请检查服务器IP和端口号是否正确", "系统信息", JOptionPane.INFORMATION_MESSAGE);
e1.printStackTrace();
} catch (IOException e1) {
JOptionPane.showMessageDialog(null,"连接服务器失败,请检查服务器IP和端口号是否正确", "系统信息", JOptionPane.INFORMATION_MESSAGE);
e1.printStackTrace();
}
}
});
btn_disconnect = new JButton("断开");
btn_disconnect.setSize(113, 27);
btn_disconnect.setLocation(684, 25);
btn_disconnect.addActionListener(new ActionListener() {
//绑定一个断开连接的监听器
@Override
public void actionPerformed(ActionEvent e) {
if(!isConnect) {
return;
}
String Offline_name = "OFFLINE@"+name;
try {
write.println(Offline_name);//将信息写进字符缓冲区
write.flush();//刷新该流的缓冲。
listModel.clear();//改变用户列表
textArea.append("服务器:用户"+name+"已下线!\n");
//将port、ip、name设为可编辑
inputbox_ip.setEditable(true);
inputbox_port.setEditable(true);
inputbox_username.setEditable(true);
isConnect = false;//更改连接状态
accept.interrupt();//中断客户端接收线程
write.close();
buf.close();
//关闭客户的输出流和输入流
out.close();
in.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
btn_send = new JButton("发送");
btn_send.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// System.out.println("-----------------------------------------");
// 创建一个发送的监听
if(!isConnect) {
JOptionPane.showMessageDialog(null,"请先连接服务器!", name, JOptionPane.INFORMATION_MESSAGE);
return;
}
String send_massage = inputbox.getText();
inputbox.setText("");//将消息框置为空
if(send_massage.equals("")) {
JOptionPane.showMessageDialog(null,"您输入的内容为空!", name, JOptionPane.INFORMATION_MESSAGE);
return;
}
textArea.append("我:"+send_massage+"\n");
send_massage = "SEND_MESSAGE@"+send_massage;
write = new PrintWriter(out);
write.println(send_massage);//将发送的信息写进字符缓冲区
write.flush();//刷新缓冲。
}
});
listModel = new DefaultListModel<String>();
JList<String> list = new JList<String>(listModel);
list.addListSelectionListener(new ListSelectionListener() {
//增加一个监听,当鼠标点击用户时
public void valueChanged(ListSelectionEvent e) {
// 鼠标点击
if (!e.getValueIsAdjusting()) {
// 获取所有被选中的选项下标
int index = list.getSelectedIndex();
if (index >= 0) {
String select_Name = listModel.getElementAt(index); // 获取选项数据(私聊名字)
//System.out.println("私聊用户:"+selectName);
//不能私聊自己
if(!select_Name.equals(name)) {
inputbox.setText(" "+"@"+select_Name+"@");
}
}
}
}
});
//连接信息部分的界面
northPanel = new JPanel();
northPanel.setLayout(null);
northPanel.setBounds(new Rectangle(0, 0, 811, 71));
// northPanel.setLayout(new GridLayout(1,7));
northPanel.setBorder(new TitledBorder("连接信息"));//设置标题Title
JLabel name_name = new JLabel("姓名:");
name_name.setSize(54, 21);
name_name.setLocation(14, 29);
northPanel.add(name_name);
northPanel.add(inputbox_username);
JLabel ip_ip = new JLabel("服务器IP:");
ip_ip.setSize(86, 21);
ip_ip.setLocation(216, 28);
northPanel.add(ip_ip);
northPanel.add(inputbox_ip);
JLabel port_port = new JLabel("端口:");
port_port.setSize(54, 21);
port_port.setLocation(405, 29);
northPanel.add(port_port);
northPanel.add(inputbox_port);
northPanel.add(btn_connect);
northPanel.add(btn_disconnect);
//中间的滚动面板部分
//左边在线用户面板部分
leftscrollPanel = new JScrollPane(list);
leftscrollPanel.setBorder(new TitledBorder("在线用户"));
//右边消息显示区面板部分
rightscrollPanel = new JScrollPane(textArea);
rightscrollPanel.setBorder(new TitledBorder("消息显示区"));
//分割中间部分面板
centerSplit =new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftscrollPanel,rightscrollPanel);
centerSplit.setSize(811, 314);
centerSplit.setLocation(0, 72);
centerSplit.setDividerLocation(100); //设置分割的位置为从左向右100
//底部(南)面板界面
southPanel = new JPanel(new BorderLayout());
southPanel.setSize(811, 64);
southPanel.setLocation(0, 387);
southPanel.setBorder(new TitledBorder("写信息"));
southPanel.add(inputbox,"Center"); //信息输入位置
southPanel.add(btn_send,"East"); //发送按钮
frame = new JFrame("客户端");
// frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().setLayout(null);
frame.getContentPane().add(northPanel,"North");
frame.getContentPane().add(centerSplit,"Center");
frame.getContentPane().add(southPanel,"South");
frame.setSize(840,500);
int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
frame.setLocation((screen_width-frame.getWidth())/2,(screen_height-frame.getWidth())/2);
frame.setVisible(true); //设置可见
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
if(isConnect) {
String info_send = "OFFLINE@"+"我下线了";
write.println(info_send);将信息写进字符缓冲区
write.flush();//刷新该流的缓冲
isConnect = false;
}
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ClientSide frame = new ClientSide();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
//接收客户端
public class Accept extends Thread{
private Socket socket;
public Accept( Socket socket) {
this.socket = socket;
}
public void run() {
try {
// 打开客户端输入流
in = socket.getInputStream();
buf = new BufferedReader(new InputStreamReader(in));//字符输入流
while(true) {
if(!isConnect) {
return;
}
String info_accept = buf.readLine();
StringTokenizer str = new StringTokenizer(info_accept,"@");//分割接收的信息,提取命令
String order = str.nextToken();//命令
String send_massage = str.nextToken();
//消息种类分类
switch(order) {
//将新上线的用户打印到在线人数区。
case "NEWCLIENT":
listModel.addElement(send_massage);
break;
//将接收的消息打印到客户的消息显示区
case "SEND_MESSAGE":
textArea.append(send_massage+"\n");
break;
//弹出服务器发送的警告
case "WARNING":
textArea.append(send_massage+"\n");
JOptionPane.showMessageDialog(null,send_massage, name, JOptionPane.INFORMATION_MESSAGE);
break;
//接收其它用户下线信息,并更新在线人数列表
case "OFFLINE":
listModel.removeElement(send_massage);
textArea.append("服务器:"+send_massage+"已下线\n");
// btn_disconnect.setEnabled(false);
break;
//将接收的私聊消息打印到客户的消息显示区
case " ":
textArea.append(send_massage+"\n");
break;
//被踢用户显示被踢消息
case "Kick":
isConnect = false;
inputbox_ip.setEditable(true);
inputbox_port.setEditable(true);
inputbox_username.setEditable(true);
listModel.clear();
textArea.append("服务器:您已被踢出群聊\n");
write.close();
buf.close();
out.close();
in.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}