1.首先分享界面效果
有服务端用户显示界面,客户端好友列表界面。
还有客户端的聊天界面。
2.主要功能:好友管理(连接数据库实现),点对点聊天,密码管理(文件实现),好友上线自动提示,表情和文件。
3.连接的数据库是phpstudy安装的mysql,表结构如下。(为了方便只能实现添加5位好友)
。
4.源代码目录结构如下,分为client和server两部分,都由main类启动。image和receive-file用于保存接收和发送的文件或表情(即图片),其中服务端的user.txt保存用户密码信息,联合数据库实现登录功能。
5.这里贴上客户端和服务端的main类代码。
package src.client;
import java.net.*;
import java.io.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class ClientMain {
static Socket socket = null;//连接服务器
static DataInputStream inputFromServer = null;
static DataOutputStream outputToServer = null;
static Thread receiveRequestThread;
//好友列表
static String[] columnNames = { "好友昵称", "在线状态" };
static Object[][] rowData = {};
static DefaultTableModel defaultModel = new DefaultTableModel(rowData, columnNames);
public static void main(String[] args){
new ClientMain();
}
public ClientMain(){
String text[] = inputText();//登录界面,获取输入信息
linkServer(text[0], text[1], Integer.parseInt(text[2]), text[3]);// 连接服务器
new WorkWindow(text[0]);//显示好友列表
receiveRequestThread = new Thread(new WorkReceive());//创建接收请求的线程
receiveRequestThread.start();
}
//登录界面
public String[] inputText(){
//初始化文本输入
JTextField textName = new JTextField(10);
textName.setText("张三");
JPasswordField textPassword = new JPasswordField(10);
textPassword.setText("aS1234567");
JTextField textAddress = new JTextField(16);
textAddress.setText("127.0.0.1");
JTextField textPort = new JTextField(5);
textPort.setText("9001");
//接收输入
String text[] = new String[4];
boolean goon = true;
while(goon){
//登录窗口
int a = JOptionPane.showConfirmDialog(null,
new Object[] { "请输入你的昵称(新用户将自动注册)", textName, "请输入你的登录密码", textPassword,
"请输入你要连接的地址: ", textAddress, "请输入端口号: ", textPort},
"登录",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if(a == JOptionPane.OK_OPTION){ //点击确认
text[0] = textName.getText();
text[1] = textAddress.getText().trim();
text[2] = textPort.getText().trim();
text[3] = new String(textPassword.getPassword());
//检验输入
if (text[0].length() < 1 || text[0].length() > 10) {
JOptionPane.showMessageDialog(null, "昵称长度应为1-10个字符", "输入错误", JOptionPane.ERROR_MESSAGE);
continue;
}
if(!text[3].matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\\S+$).{8,}$")) {
JOptionPane.showMessageDialog(null, "密码必须包含至少一个小写字母、一个大写字母、一个数字,并且长度至少为8位", "输入错误", JOptionPane.ERROR_MESSAGE);
continue;
}
if(Integer.parseInt(text[2]) > 65535 || Integer.parseInt(text[2]) < 1024){
JOptionPane.showMessageDialog(null, "端口号不可用", "输入错误", JOptionPane.ERROR_MESSAGE);
continue;
}
if(!text[1].matches("(\\d{1,3}\\.){3}\\d{1,3}")) {
JOptionPane.showMessageDialog(null, "请输入正确的IP地址", "输入错误", JOptionPane.ERROR_MESSAGE);
continue;
}
goon = false;
}else{
System.exit(0);
}
}
return text;
}
// 连接服务器
public void linkServer(String name, String ip, int port, String password) {
try {
socket = new Socket(ip, port);
inputFromServer = new DataInputStream(socket.getInputStream());
outputToServer = new DataOutputStream(socket.getOutputStream());
outputToServer.writeUTF(name);
outputToServer.writeUTF(password);
outputToServer.flush();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "服务器不在线或端口错误", "连接失败", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
try {
String str = inputFromServer.readUTF();
if(str.equals("登录失败")){//服务端检测到密码错误
//退出程序
JOptionPane.showMessageDialog(null, "密码错误", "警告", JOptionPane.ERROR_MESSAGE);
inputFromServer.close();
outputToServer.close();
socket.close();
System.exit(0);
}
//接收好友列表
int num = inputFromServer.readInt();
String friendInfo[] = new String[num];
for(int i=0; i<num; i++){
friendInfo[i] = inputFromServer.readUTF();
String state = inputFromServer.readUTF();
Object[] row = {friendInfo[i], state};
defaultModel.addRow(row);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package src.server;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import java.io.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class ServerMain extends JFrame {
public static int port = 9001;
ServerSocket serverSocket = null;
Socket socket = null;
Thread thread;
static Map<String, Socket> userSocketMap = new HashMap<>();
// 界面显示客户端信息
static String[] columnNames = { "用户名", "上线时间", "ip", "状态" };
static Object[][] rowData = {};
static DefaultTableModel defaultModel = new DefaultTableModel(rowData, columnNames);
JTable table = new JTable(defaultModel);
JScrollPane JSPanel = new JScrollPane(table);
JPanel SPanel = new JPanel();
public static void main(String[] args) {
new ServerMain();
}
public ServerMain(){
// 设置表格外观
table.getTableHeader().setBackground(new Color(135, 206, 250));
table.getTableHeader().setForeground(Color.WHITE);
table.setBackground(new Color(173, 216, 230));
Font tableFont = new Font("UTF", Font.BOLD, 12);
table.setFont(tableFont);
table.getTableHeader().setFont(tableFont);
table.setRowHeight(35);
//设置窗口
this.setTitle("CL服务器");
this.setBounds(50, 150, 300, 600);
this.setResizable(false);
SPanel.add(JSPanel);
this.add(SPanel, BorderLayout.SOUTH);
this.pack();
this.addWindowListener(new CloseSrever());
this.setVisible(true);
//启动服务器,开始接收客户端连接
acceptClient();
}
// 监听类 处理屏幕关闭
class CloseSrever extends WindowAdapter {
public void windowClosing(WindowEvent e) {
try {
// 通知在线的各客户端
for (int i = 0; i < defaultModel.getRowCount(); i++) {
if (defaultModel.getValueAt(i, 3).equals("在线")) {
Socket socket = userSocketMap.get(defaultModel.getValueAt(i, 0));
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
outputToClient.writeUTF("exit");
outputToClient.flush();
}
}
serverSocket.close();
System.exit(0);
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
//启动服务器,开始接收客户端连接
public void acceptClient() {
boolean goon = true;
//打开端口
try {
serverSocket = new ServerSocket(port);
} catch (IOException e1) {
JOptionPane.showMessageDialog(null, "端口已被使用,请重新运行", "启动失败", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
//开启监听
try {
while (goon) {
socket = serverSocket.accept();
if(socket != null){
HandleClient hc = new HandleClient(socket);
thread = new Thread(hc);
thread.start();
}
}
} catch (IOException e) {
e.printStackTrace();
goon = false;
}
}
}
资源已绑定在上传文件中,也可以留下评论免费获取。