java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

时间:2021-07-13 00:57:03

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

  启动界面如下图:

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

首先启动服务器:

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

客户端登陆,登陆成功后为:

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

默认发送是全部用户,是多人发送。  当在边列表里面选择了用户后,可以与此用户建立点对点链接进行聊天,可以发送文件。

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

用户在线离线状态会实时更新,如果离线,则存为离线消息。当下次上线的时候,会接受到离线消息

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

从一个用户接受文件的同时,还可以接受从服务器发过来的文件

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

接受文件完成后,显示记录,并显示保存目录

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

消息发送演示

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

服务器端代码:

 import sun.misc.BASE64Encoder;

 import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
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.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.StringTokenizer; import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
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; public class Server { private JFrame frame;
private JTextArea contentArea;
private JTextField txt_message;
private JTextField txt_max;
private JTextField txt_port;
private JButton btn_start;
private JButton btn_stop;
private JButton btn_send;
private JButton btn_send_file;
private JPanel northPanel;
private JPanel southPanel;
private JPanel sendPanel;
private JScrollPane rightPanel;
private JScrollPane leftPanel;
private JScrollPane rightPanel2;
private JSplitPane centerSplit;
private JSplitPane centerSplit2;
private JList userList;
private JList all_userList;
private DefaultListModel listModel;
private static DefaultListModel all_listModel; private ServerSocket serverSocket;
private ServerThread serverThread;
private ArrayList<ClientThread> clients;//客户线程数组 private boolean isStart = false;//标志服务器是否启动或关闭 private int sendfor_who = 0;//监听左边jlist,保存给哪个用户发消息 // 主方法,程序执行入口
public static void main(String[] args) { new Server(); try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); } catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
} /**利用MD5进行加密
* @param str 待加密的字符串
* @return 加密后的字符串
* @throws NoSuchAlgorithmException 没有这种产生消息摘要的算法
* @throws UnsupportedEncodingException
*/
public String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
//确定计算方法
MessageDigest md5=MessageDigest.getInstance("MD5");
BASE64Encoder base64en = new BASE64Encoder();
//加密后的字符串
String newstr=base64en.encode(md5.digest(str.getBytes("utf-8")));
return newstr;
} /**判断用户密码是否正确
* @param newpasswd 用户输入的密码
* @param oldpasswd 数据库中存储的密码--用户密码的摘要
* @return
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public boolean checkpassword(String newpasswd,String oldpasswd) throws NoSuchAlgorithmException, UnsupportedEncodingException{
if(EncoderByMd5(newpasswd).equals(oldpasswd))
return true;
else
return false;
} /**
* 刚服务器突然关闭时,把所有用户状态置为离线
*/
public void set_user_state_off() {
try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); int id = 0;
String selectSql = "UPDATE user SET state = 0";
stmt.executeUpdate(selectSql);
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
} /**
* 更新用户状态
*/
public void user_name_update() { try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); all_listModel.removeAllElements();
all_listModel.addElement("全部用户"); String username_db;
int state = 0;
//查询用户名
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
username_db = selectRes.getString("username");
state = selectRes.getInt("state");
if (state == 1) {
all_listModel.addElement(username_db + "---(在线)");
} } selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
username_db = selectRes.getString("username");
state = selectRes.getInt("state");
if (state == 0) {
all_listModel.addElement(username_db + "---(离线)");
} }
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
} } /**
* 执行消息发送
*/
public void send() {
if (!isStart) {
JOptionPane.showMessageDialog(frame, "服务器还未启动,不能发送消息!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
// if (clients.size() == 0) {
// JOptionPane.showMessageDialog(frame, "没有用户在线,不能发送消息!", "错误",
// JOptionPane.ERROR_MESSAGE);
// return;
// }
String message = txt_message.getText().trim();
if (message == null || message.equals("")) {
JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
sendServerMessage(message, sendfor_who);// 群发服务器消息
//contentArea.append("对 "+listModel.getElementAt(sendfor_who)+" 说:" + txt_message.getText() + "\r\n");
txt_message.setText(null);
} // 构造放法
public Server() {
SelecTry selectIndex = new SelecTry();
frame = new JFrame("服务器");
contentArea = new JTextArea();
contentArea.setEditable(false);
contentArea.setForeground(Color.blue);
txt_message = new JTextField();
txt_max = new JTextField("30");
txt_port = new JTextField("6666");
btn_start = new JButton("启动");
btn_stop = new JButton("停止");
btn_send = new JButton("发送");
btn_send_file = new JButton("文件");
btn_stop.setEnabled(false);
listModel = new DefaultListModel();
all_listModel = new DefaultListModel();
//listModel.addElement("全部用户");
userList = new JList(all_listModel);//listModel
userList.addListSelectionListener(selectIndex); user_name_update();//更新用户状态 // all_userList = new JList(all_listModel); southPanel = new JPanel(new BorderLayout());
sendPanel = new JPanel(new BorderLayout());
southPanel.setBorder(new TitledBorder("写消息"));
southPanel.add(txt_message, "Center");
sendPanel.add(btn_send, BorderLayout.NORTH);
sendPanel.add(btn_send_file, BorderLayout.SOUTH); southPanel.add(sendPanel, "East"); leftPanel = new JScrollPane(userList);
leftPanel.setBorder(new TitledBorder("用户列表")); // rightPanel2 = new JScrollPane(all_userList);
// rightPanel2.setBorder(new TitledBorder("全部用户")); rightPanel = new JScrollPane(contentArea);
rightPanel.setBorder(new TitledBorder("消息显示区")); centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel,
rightPanel);
centerSplit.setDividerLocation(150); // centerSplit2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, centerSplit,
// rightPanel2);
// centerSplit2.setDividerLocation(450); northPanel = new JPanel();
northPanel.setLayout(new GridLayout(1, 6));
northPanel.add(new JLabel(" 人数上限"));
northPanel.add(txt_max);
northPanel.add(new JLabel(" 端口"));
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.add(rightPanel2,BorderLayout.EAST);
frame.add(southPanel, "South");
frame.setSize(600, 400);
//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);// 退出程序
}
}); // 文本框按回车键时事件
txt_message.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send();
}
}); // 单击发送按钮时事件
btn_send.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
send();
}
}); //单机文件按钮时事件
btn_send_file.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//文件选择对话框启动,当选择了文件以后给每一个client发送文件
JFileChooser sourceFileChooser = new JFileChooser(".");
sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int status = sourceFileChooser.showOpenDialog(frame);
File sourceFile = new File(sourceFileChooser.getSelectedFile().getPath());
//服务器text area提示
contentArea.append("发送文件:" + sourceFile.getName() + "\r\n");
for (int i = clients.size() - 1; i >= 0; i--) {
SendFileThread sendFile = new SendFileThread(frame, clients.get(i).socket, "服务器", sourceFileChooser, status);
sendFile.start();
//client端提示
clients.get(i).getWriter().println("服务器发送一个文件:" + sourceFile.getName() + "(多人发送)");
clients.get(i).getWriter().flush();
} }
}); // 单击启动服务器按钮时事件
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("人数上限为正整数!");
}
try {
port = Integer.parseInt(txt_port.getText());
} catch (Exception e1) {
throw new Exception("端口号为正整数!");
}
if (port <= 0) {
throw new Exception("端口号 为正整数!");
}
serverStart(max, port);
contentArea.append("服务器已成功启动! 人数上限:" + max + ", 端口:" + port
+ "\r\n");
JOptionPane.showMessageDialog(frame, "服务器成功启动!");
btn_start.setEnabled(false);
txt_max.setEnabled(false);
txt_port.setEnabled(false);
btn_stop.setEnabled(true);
listModel.addElement("全部用户");
user_name_update();
} 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);
}
}
});
} /**
* 监听左边jlist选择的是哪一个用户
*/
class SelecTry implements ListSelectionListener {
int change = 0, who; public void valueChanged(ListSelectionEvent e) {
//System.out.println("you selected:"+listModel.getElementAt(userList.getSelectedIndex()));
sendfor_who = userList.getSelectedIndex();
} } /**
* 找回密码模块
*
* @param username
* @param youxiang
* @param new_password
* @return
*/
public int user_forget(String username, String youxiang, String new_password) {
try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); String codingpassword = EncoderByMd5(new_password); //查询数据,不能有相同的用户名
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
int userid = selectRes.getInt("Id");
String username_db = selectRes.getString("username");
String youxiang_db = selectRes.getString("youxiang");
if (username.equals(username_db)) {
if (youxiang_db.equals(youxiang)) {
//更新一条数据
String updateSql = "UPDATE user SET password = '" + codingpassword + "' WHERE Id = " + userid + "";
long updateRes = stmt.executeUpdate(updateSql);
return 1;
} }
}
return 0;
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
return 0;
} /**
* 注册模块
*
* @param username
* @param password
* @param youxiang
* @return
*/
public int user_register(String username, String password, String youxiang) { try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); String codingPassword = EncoderByMd5(password); //查询数据,不能有相同的用户名
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
String username_db = selectRes.getString("username");
if (username.equals(username_db)) {
return 2;
}
}
//新增一条数据
stmt.executeUpdate("INSERT INTO user (username, password,youxiang) VALUES ('" + username + "', '" + codingPassword + "','" + youxiang + "')");
all_listModel.addElement(username);
return 1;
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
return 0;
} /**
* 当有用户下线时,在服务器改变状态
*
* @param name
* @return
*/
public int user_offLine(String name) {
try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); //
String username_fromDb;
int id = 0;
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
username_fromDb = selectRes.getString("username");
id = selectRes.getInt("Id");
if (name.equals(username_fromDb)) {
selectSql = "UPDATE user SET state = 0 WHERE Id = " + id + "";
stmt.executeUpdate(selectSql);
selectSql = "UPDATE user SET serverPort = 0 WHERE Id = " + id + "";
stmt.executeUpdate(selectSql);
selectSql = "UPDATE user SET ipAdres = '' WHERE Id = " + id + "";
stmt.executeUpdate(selectSql);
return 1;
}
}
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
return 0;
} /**
* 登陆模块
*
* @param username
* @param password
* @return
*/
public int user_login(String username, String password,int serverPort,String myIP) {
try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); //
String username_fromDb;
String password_fromDb;
String codingNewPassword;
int state = 0, id = 0;
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
username_fromDb = selectRes.getString("username");
password_fromDb = selectRes.getString("password");
codingNewPassword = EncoderByMd5(password);
id = selectRes.getInt("Id");
state = selectRes.getInt("state");
if (username.equals(username_fromDb) && codingNewPassword.equals(password_fromDb)) {
if (state == 0) {
selectSql = "UPDATE user SET state = 1 WHERE Id = " + id + "";
stmt.executeUpdate(selectSql);
selectSql = "UPDATE user SET serverPort = " + serverPort + " WHERE Id = " + id + "";
stmt.executeUpdate(selectSql);
selectSql = "UPDATE user SET ipAdres = '" + myIP + "' WHERE Id = " + id + "";
stmt.executeUpdate(selectSql);
return 1;//还没有登陆,可以登陆
} else {
return 2;//已登陆状态,无法登陆
} }
}
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
return 0;
} /**
* 启动服务器
*
* @param max
* @param port
* @throws java.net.BindException
*/
public void serverStart(int max, int port) throws java.net.BindException {
try {
clients = new ArrayList<ClientThread>();
serverSocket = new ServerSocket(port);
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;
set_user_state_off();
user_name_update();
} catch (IOException e) {
e.printStackTrace();
isStart = true;
}
} /**
* 群发服务器消息
*
* @param message
* @param who
*/
public void sendServerMessage(String message, int who) {
if (who == 0) {
StringTokenizer stringTokenizer;
int flag = 0;
for (int i = all_listModel.size(); i > 0; i--) {
flag = 0;
String msg = all_listModel.getElementAt(i - 1) + "";
stringTokenizer = new StringTokenizer(
msg, "---");
String user_name = stringTokenizer.nextToken();
for (int j = clients.size() - 1; j >= 0; j--) {
if (user_name.equals(clients.get(j).getUser().getName())) {
clients.get(j).getWriter().println("服务器对你说 " + message);
clients.get(j).getWriter().flush();
flag = 1;//该用户在线状态,已发出去
break;
}
}
if (flag == 0) {
//用户离线状态,则留言
send_messageTo_board("服务器", user_name, message);
}
}
contentArea.append("对 全部用户 发送:" + message + "\r\n");
} else {
int flag = 0;
String msg = "" + all_listModel.getElementAt(who);
StringTokenizer stringTokenizer = new StringTokenizer(
msg, "---");
String user_name = stringTokenizer.nextToken();
for (int i = clients.size() - 1; i >= 0; i--) {
if (user_name.equals(clients.get(i).getUser().getName())) {
clients.get(i).getWriter().println("服务器对你说 " + message);
clients.get(i).getWriter().flush();
flag = 1;//该用户在线状态,已发出去
break;
}
}
if (flag == 0) {
// JOptionPane.showMessageDialog(frame, "该用户不在线,已存为留言板!", "错误",
// JOptionPane.ERROR_MESSAGE);
send_messageTo_board("服务器", user_name, message);
contentArea.append("对 " + user_name + " 留言:" + message + "\r\n");
} else {
contentArea.append("对 " + user_name + " 说:" + message + "\r\n");
}
} } /**
* 用户不在线时,离线消息保存到服务器里面
* @param send_from
* @param send_for
* @param message
* @return
*/
public int send_messageTo_board(String send_from, String send_for, String message) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
String msg = send_from + "#" + df.format(new Date()) + "#" + message + "#";
try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); //查询数据,不能有相同的用户名
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
int Id = selectRes.getInt("Id");
String username_db = selectRes.getString("username");
if (send_for.equals(username_db)) {
String old_message = selectRes.getString("message");
String updateSql = "UPDATE user SET message = '" + old_message + msg + "' WHERE Id = " + Id + "";
stmt.executeUpdate(updateSql);
return 1;
}
}
return 0;
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
return 0;
} /**
* 服务器线程
*/
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(), st.nextToken());
// 反馈连接成功信息
w.println("MAX#服务器:对不起," + user.getName()
+ user.getIp() + ",服务器在线人数已达上限,请稍后尝试连接!");
w.flush();
// 释放资源
r.close();
w.close();
socket.close();
continue;
}
ClientThread client = new ClientThread(socket);
client.start();// 开启对此客户端服务的线程
client.getUser().setState(1);//在线状态
clients.add(client);
listModel.addElement(client.getUser().getName());// 更新在线列表
contentArea.append(client.getUser().getName()
+ client.getUser().getIp() + "上线!\r\n");
// user_name_update();
} 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(), st.nextToken());
// 反馈连接成功信息
writer.println(user.getName() + user.getIp() + "与服务器连接成功!");
writer.flush(); } catch (IOException e) {
e.printStackTrace();
}
} @SuppressWarnings("deprecation")
public void run() {// 不断接收客户端的消息,进行处理。
String message = null;
while (true) {
try {
message = reader.readLine();// 接收客户端消息
StringTokenizer stringTokenizer = new StringTokenizer(
message, "#");
String command = stringTokenizer.nextToken();// 命令
if (command.equals("CLOSE"))// 下线命令
{
contentArea.append(this.getUser().getName()
+ this.getUser().getIp() + "下线!\r\n");
// 断开连接释放资源
user_offLine(this.getUser().getName());
this.getUser().setState(0);
reader.close();
writer.close();
socket.close(); user_name_update();//更新用户状态 //反馈用户状态
String liststr = "";
for (int j = 1; j < all_listModel.size(); j++) {
liststr += all_listModel.get(j) + "#";
}
// 向所有在线用户发送该用户上线命令
for (int j = clients.size()-1 ; j >= 0; j--) {
clients.get(j).getWriter().println(
"USERLIST#" + all_listModel.size() + "#" + liststr);
clients.get(j).getWriter().flush();
}
//user_name_update();//更新用户状态 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 if (command.equals("USERLOGIN")) {
String username = stringTokenizer.nextToken();
String password = stringTokenizer.nextToken();
int serverPort = Integer.parseInt(stringTokenizer.nextToken());
String myIP = stringTokenizer.nextToken();
int i = user_login(username, password,serverPort,myIP);
if (1 == i) {
user_name_update();
String msg = get_message(username);
if (msg.equals("")) {
writer.println("USERLOGIN#OK#");
writer.flush();
} else {
writer.println("USERLOGIN#OK#" + msg);
writer.flush();
} //反馈用户状态
String temp = "";
for (int j = 1; j < all_listModel.size(); j++) {
temp += all_listModel.get(j) + "#";
}
// 向所有在线用户发送该用户上线命令
for (int j = clients.size()-1 ; j >= 0; j--) {
clients.get(j).getWriter().println(
"USERLIST#" + all_listModel.size() + "#" + temp);
clients.get(j).getWriter().flush();
} } else if (2 == i) {
writer.println("USERLOGIN#ALREADY");
writer.flush();
} else {
writer.println("USERLOGIN#NO");
writer.flush(); }
//user_name_update();
} else if (command.equals("USERZHUCE")) {
String username = stringTokenizer.nextToken();
String password = stringTokenizer.nextToken();
String youxiang = stringTokenizer.nextToken();
int i = user_register(username, password, youxiang);
if (1 == i) {
writer.println("USERZHUCE#OK");
writer.flush();
contentArea.append("有新用户注册! 用户名:" + username + "\r\n");
user_name_update();//更新用户状态
} else if (i == 2) {
writer.println("USERZHUCE#exict");
writer.flush();
} else {
writer.println("USERZHUCE#NO");
writer.flush();
}
} else if (command.equals("USERFORGET")) {
String username = stringTokenizer.nextToken();
String youxiang = stringTokenizer.nextToken();
String new_password = stringTokenizer.nextToken();
int i = user_forget(username, youxiang, new_password);
if (1 == i) {
//JOptionPane.showMessageDialog(frame, "登陆成功!" );
writer.println("USERFORGET#OK");
writer.flush();
contentArea.append(" 用户:" + username + " 修改密码!\r\n");
} else if (i == 2) {
writer.println("USERFORGET#YOUXIANG_WRONG");
writer.flush();
} else if (i == 3) {
writer.println("USERFORGET#NAME_NO_exict");
writer.flush();
} else {
writer.println("USERFORGET#NO");
writer.flush();
}
} else if (command.equals("P2P")) {
String username = stringTokenizer.nextToken();
int i = get_user_serverPort(username);
String ip = get_user_serverIP(username);
if(i!=0){
writer.println("P2P#OK#"+username+"#"+i+"#"+ip);
writer.flush();
}else{
writer.println("P2P#NO#"+username);
writer.flush();
}
}else if(command.equals("LIXIAN")){
String username_sent = stringTokenizer.nextToken();
String username_receive = stringTokenizer.nextToken();
String msg = stringTokenizer.nextToken();
send_messageTo_board(username_sent,username_receive,msg);
System.out.println("离线发送ok");
} else {
dispatcherMessage(message);// 转发消息
}
} catch (IOException e) {
e.printStackTrace();
}
}
} public int get_user_serverPort(String user_name){
try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); //查询数据,不能有相同的用户名
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
String username_db = selectRes.getString("username");
if (user_name.equals(username_db)) {
int serverPort = selectRes.getInt("serverPort");
return serverPort;
}
}
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
return 0;
} public String get_user_serverIP(String user_name){
try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); //查询数据,不能有相同的用户名
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
String username_db = selectRes.getString("username");
if (user_name.equals(username_db)) {
String serverIP = selectRes.getString("ipAdres");
return serverIP;
}
}
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
return "";
} public String get_message(String name) {
try {
Connection con = null; //定义一个MYSQL链接对象
Class.forName("com.mysql.jdbc.Driver").newInstance();//MYSQL驱动
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/server_db", "root", "root"); //链接本地MYSQL
Statement stmt; //创建声明
stmt = con.createStatement(); //查询数据,不能有相同的用户名
String selectSql = "SELECT * FROM user";
ResultSet selectRes = stmt.executeQuery(selectSql);
while (selectRes.next()) { //循环输出结果集
int Id = selectRes.getInt("Id");
String username_db = selectRes.getString("username");
if (name.equals(username_db)) {
String message = selectRes.getString("message");
String updateSql = "UPDATE user SET message = '' WHERE Id = " + Id + "";
stmt.executeUpdate(updateSql);
return message;
}
}
return "";
} catch (Exception e) {
System.out.print("MYSQL ERROR:" + e.getMessage());
}
return "";
} // 转发消息
public void dispatcherMessage(String message) {
StringTokenizer stringTokenizer = new StringTokenizer(message, "#");
String source = stringTokenizer.nextToken();
String owner = stringTokenizer.nextToken();
String content = stringTokenizer.nextToken(); if (owner.equals("ALL")) {// 群发
message = source + "说:" + content;
contentArea.append(message + "\r\n");
for (int i = clients.size() - 1; i >= 0; i--) {
clients.get(i).getWriter().println(message + "(多人发送)");
clients.get(i).getWriter().flush();
}
} else {
for (int i = clients.size() - 1; i >= 0; i--) {
if (clients.get(i).user.getName().equals(owner)) {
clients.get(i).getWriter().println(owner + " 对你说: " + content);
clients.get(i).getWriter().flush();
//contentArea.append(owner+" 对 "+ clients.get(i).user.getName()+ " 说 :"+ content+"\r\n");
}
if (clients.get(i).user.getName().equals(source)) {
clients.get(i).getWriter().println("对 " + source + " 说: " + content);
clients.get(i).getWriter().flush();
}
}
}
}
}
}
 import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket; import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.ProgressMonitor;
import javax.swing.ProgressMonitorInputStream; public class SendFileThread extends Thread {
private Socket clientSocket;
private String name;
JFileChooser sourceFileChooser;
int status;
JFrame JFrame; public SendFileThread(JFrame frame, Socket socket, String name, JFileChooser sourceFileChooser, int status) {
this.clientSocket = socket;
this.name = name;
this.sourceFileChooser = sourceFileChooser;
this.status = status;
this.JFrame = frame;
} public void run() {
// JFileChooser sourceFileChooser = new JFileChooser(".");
// sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
// int status = sourceFileChooser.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION) {
File sourceFile = new File(sourceFileChooser.getSelectedFile().getPath());
String sourceFilePath = sourceFile.getAbsolutePath();
String fileName = sourceFile.getName();
//System.out.println(sourceFilePath+"\\"+fileName);
try {
PrintWriter sendToClient = new PrintWriter(clientSocket.getOutputStream());
BufferedReader getFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
ServerSocket fileSenderSocket = null;
try {
fileSenderSocket = new ServerSocket(0);
} catch (IOException ex1) {
JOptionPane.showMessageDialog(JFrame, "无法分配端口以发送此文件!", "错误", JOptionPane.ERROR_MESSAGE);
}
sendToClient.println("FILE#" + fileSenderSocket.getLocalPort() + "#" + fileName + "#"
+ String.valueOf(sourceFile.length()) + "#" + clientSocket.getInetAddress().getHostAddress() + "#" + name);
sendToClient.flush();
//System.out.println("Sender: "+fileSenderSocket.getLocalSocketAddress());
Socket fileReceiverSocket = fileSenderSocket.accept(); BufferedReader getFromReceiver = null;
PrintWriter sendToReceiver = null;
try {
getFromReceiver = new BufferedReader(new InputStreamReader(fileReceiverSocket.getInputStream()));
sendToReceiver = new PrintWriter(fileReceiverSocket.getOutputStream());
} catch (IOException ex) {
} finally {
}
String judge = getFromReceiver.readLine();
if (judge.equals("accepted")) {
DataOutputStream sendFileToReceiver = new DataOutputStream(new BufferedOutputStream(fileReceiverSocket.getOutputStream()));
ProgressMonitorInputStream monitor;
FileInputStream sendFileStream = null;
try {
sendFileStream = new FileInputStream(sourceFile);
} catch (FileNotFoundException ex) {
sendToReceiver.flush();
sendFileToReceiver.writeByte(0);
sendFileToReceiver.flush();
return;
}
monitor = new ProgressMonitorInputStream(JFrame, "正在发送: " + fileName, sendFileStream);
ProgressMonitor progressMonitor = monitor.getProgressMonitor(); int read_unit = 500;
long fileSize = monitor.available();
int readed = 0;
byte[] data = new byte[read_unit];
try {
sendFileToReceiver.writeByte(1);
sendFileToReceiver.flush();
while (monitor.available() > 0) {
int in = monitor.read(data);
readed += in;
float process = (float) readed / fileSize * 100;
progressMonitor.setNote(process + " % 完成");
if (in > 0) {
sendFileToReceiver.write(data, 0, in);
}
}
sendFileToReceiver.flush();
} catch (IOException e) {
JOptionPane.showMessageDialog(JFrame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE);
} finally {
if (sendFileStream != null)
try {
sendFileStream.close();
monitor.close();
} catch (IOException e) {
}
}
try {
fileReceiverSocket.close();
} catch (IOException ex1) {
}
} else if (judge.equals("refused")) {
JOptionPane.showMessageDialog(JFrame, "对方拒绝接受文件 " + fileName, "错误!", JOptionPane.INFORMATION_MESSAGE);
} } catch (IOException ex) {
} finally {
}
}
}
}
 //用户信息类
public class User{
private String name;
private String ip;
private int state; public User(String name, String ip) {
this.name = name;
this.ip = ip;
state = 0;
} 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;
} public int getState() {
return state;
} public void setState(int state) {
this.state = state;
}
}

数据库:

java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

是通过MD5加密保存。

客户端代码:

 package com.company;

 import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
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.*;
import java.net.BindException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer; import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; //import socket_chat_server.Server.ClientThread;
//import socket_chat_server.Server.SelecTry; public class Client{ private JPanel sendPanel;
private JButton btn_send_file;
private JFrame frame;
private JList userList;
private JTextArea textArea;
private JTextField textField;
private JTextField txt_port;
private JTextField txt_hostIp;
private JTextField txt_name;
private JButton btn_start;
private JButton btn_stop;
private JButton btn_send;
private JPanel northPanel;
private JPanel southPanel;
private JScrollPane rightScroll;
private JScrollPane leftScroll;
private JSplitPane centerSplit; private JPanel logPanle;
private JFrame loginframe;
private JLabel label_username;
private JLabel label_password;
private JTextField txt_login_name;
private JTextField txt_password;
private JTextField txt_login_ip;
private JTextField txt_login_port;
private JTextField txt_login_forget;
private JButton btn_submit;
private JButton btn_zhuce;
private JButton btn_forget_pass; private DefaultListModel listModel;
private boolean isConnected = false; private int sendfor_who;
private int server_port=0; private ServerSocket serverSocket;
private ServerThread serverThread;
private Socket socketfor_p2p;
private boolean isConnected_p2p = false;
private ArrayList<ClientThread> clients;//客户线程数组
private PrintWriter P2P_printWriter;//点对点服务的输出流
private BufferedReader P2P_bufferReader;//点对点服务的输入流
private MessageThread_P2P messageThread_for_p2p;// 负责接收p2p消息的线程
private Map<String, Boolean> P2P_connected_user = new HashMap<String, Boolean>(); private Socket socket;
private PrintWriter writer;
private BufferedReader reader;
private MessageThread messageThread;// 负责接收消息的线程
private Map<String, User> onLineUsers = new HashMap<String, User>();// 所有在线用户
private String myIP = "";//每一个客户端都有唯一的IP地址 // 主方法,程序入口
public static void main(String[] args) throws BindException {
new Client(); } class SelecTry implements ListSelectionListener
{
int change=0,who;
public void valueChanged(ListSelectionEvent e){
//System.out.println("you selected:"+listModel.getElementAt(userList.getSelectedIndex()));
sendfor_who=userList.getSelectedIndex();
isConnected_p2p = false;
} } /**
* 连接服务器
*
* @param port
* @param hostIp
* @param name
*/
public boolean connectServer_p2p(int port, String hostIp, String name) {
// 连接服务器
try {
socketfor_p2p = new Socket(hostIp, port);// 根据端口号和服务器ip建立连接
P2P_printWriter = new PrintWriter(socketfor_p2p.getOutputStream());
P2P_bufferReader = new BufferedReader(new InputStreamReader(socketfor_p2p
.getInputStream())); messageThread_for_p2p = new MessageThread_P2P(P2P_bufferReader);
messageThread_for_p2p.start();
P2P_connected_user.put(name,true);
isConnected_p2p = true;// 已经连接上了
return true;
} catch (Exception e) {
textArea.append("与端口号为:" + port + " IP地址为:" + hostIp
+ " 的服务连接失败!" + "\r\n");
isConnected_p2p = false;// 未连接上
return false;
}
} /**
* 关闭服务
*/
@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#"+frame.getTitle());
clients.get(i).getWriter().flush();
// 释放资源
clients.get(i).stop();// 停止此条为客户端服务的线程
clients.get(i).reader_ptp.close();
clients.get(i).writer_ptp.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;
}
} // 不断接收消息的线程
class MessageThread_P2P extends Thread {
private BufferedReader reader_ptp; // 接收消息线程的构造方法
public MessageThread_P2P(BufferedReader reader) {
this.reader_ptp = reader; } // 被动的关闭连接
public synchronized void closeCon() throws Exception {
System.out.println("close :*************");
// 被动的关闭连接释放资源
if (reader_ptp != null) {
reader_ptp.close();
}
if (P2P_printWriter != null) {
P2P_printWriter.close();
}
if (socketfor_p2p != null) {
socketfor_p2p.close();
}
isConnected_p2p = false;// 修改状态为断开 } public void run() {
String message = "";
while (true) {
try {
message = reader_ptp.readLine();
StringTokenizer stringTokenizer = new StringTokenizer(
message, "/#");
String command = stringTokenizer.nextToken();// 命令
if (command.equals("CLOSE"))// 服务器已关闭命令
{
String user = stringTokenizer.nextToken();
textArea.append("用户 "+user+" 已下线,p2p服务已关闭!\r\n");
closeCon();// 被动的关闭连接
JOptionPane.showMessageDialog(frame, "用户 "+user+" 已下线,p2p服务已关闭!", "错误",
JOptionPane.ERROR_MESSAGE);
return;// 结束线程
} else if (command.equals("FILE")) {
int portNumber = Integer.parseInt(stringTokenizer.nextToken());
String fileName = stringTokenizer.nextToken();
long fileSize = Long.parseLong(stringTokenizer.nextToken());
String ip = stringTokenizer.nextToken();
String Nickname = stringTokenizer.nextToken();
ReceiveFileThread receiveFile = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname);
receiveFile.start();
textArea.append("从 "+Nickname+" 接受文件:"+fileName+",大小为:"+fileSize
+"ip:"+ip+"port:"+portNumber+"\r\n");
} else {// 普通消息
textArea.append(""+message + "\r\n");
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
} /**
* 启动服务器
*
* @param port
* @throws java.net.BindException
*/
public void serverStart(int port) throws java.net.BindException {
try {
clients = new ArrayList<ClientThread>();
serverSocket = new ServerSocket(port);
serverThread = new ServerThread(serverSocket);
serverThread.start();
server_port = serverSocket.getLocalPort();
InetAddress addr = InetAddress.getLocalHost();
myIP = addr.getHostAddress();//获得本机IP
// myIP = serverSocket.getInetAddress().getHostAddress();
System.out.println("mmyIP=="+myIP+"\r\n");
} catch (BindException e) {
throw new BindException("端口号已被占用,请换一个!");
} catch (Exception e1) {
e1.printStackTrace();
throw new BindException("启动服务器异常!");
}
} /**
* 为另一个主动链接的客户端提供服务的线程
*/
class ClientThread extends Thread {
private Socket socket;
private BufferedReader reader_ptp;
private PrintWriter writer_ptp;
private User user; public BufferedReader getReader() {
return reader_ptp;
} public PrintWriter getWriter() {
return writer_ptp;
} public User getUser() {
return user;
} // 客户端线程的构造方法
public ClientThread(Socket socket) {
try {
this.socket = socket;
reader_ptp = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
writer_ptp = new PrintWriter(socket.getOutputStream()); // 接收客户端的基本用户信息
String inf = reader_ptp.readLine();
StringTokenizer st = new StringTokenizer(inf, "#");
user = new User(st.nextToken(), socket.getLocalAddress().toString());
// 反馈连接成功信息
writer_ptp.println(frame.getTitle()+" 对你说: "+user.getName()+"/"+user.getIp()+"你好!"+"与我"+frame.getTitle()+"建立链接成功!");
writer_ptp.flush();
// // 反馈当前在线用户信息
// if (clients.size() > 0) {
// String temp = "";
// for (int i = clients.size() - 1; i >= 0; i--) {
// temp += (clients.get(i).getUser().getName() + "/" + clients
// .get(i).getUser().getIp())
// + "#";
// }
// 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() + user.getIp());
// clients.get(i).getWriter().flush();
// }
} catch (IOException e) {
e.printStackTrace();
}
} @SuppressWarnings("deprecation")
public void run() {// 不断接收客户端的消息,进行处理。
String message = null;
while (true) {
try {
message = reader_ptp.readLine();// 接收客户端消息
StringTokenizer stringTokenizer = new StringTokenizer(message,"/#");
String command = stringTokenizer.nextToken();
if (command.equals("CLOSE"))// 下线命令
{
textArea.append("与"+this.getUser().getName()
+ this.getUser().getIp() + "建立连接成功!\r\n");
// 断开连接释放资源
this.getUser().setState(0);
reader.close();
writer.close();
socket.close(); } else if (command.equals("FILE")) {
int portNumber = Integer.parseInt(stringTokenizer.nextToken());
String fileName = stringTokenizer.nextToken();
long fileSize = Long.parseLong(stringTokenizer.nextToken());
String ip = stringTokenizer.nextToken();
String Nickname = stringTokenizer.nextToken();
ReceiveFileThread receiveFile = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname);
receiveFile.start();
textArea.append("从 "+Nickname+" 接受文件 :"+fileName+",大小为: "+fileSize
+" ip: "+ip+" port:"+portNumber+"\r\n");
}else {
textArea.append(user.getName()+" 对你说: "+message+"\r\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
} } /**
* 服务线程
*/
class ServerThread extends Thread {
private ServerSocket serverSocket; // 服务器线程的构造方法
public ServerThread(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
} public void run() {
while (true) {// 不停的等待客户端的链接
try {
Socket socket = serverSocket.accept();
ClientThread client = new ClientThread(socket);
client.start();// 开启对此客户端服务的线程
clients.add(client);
textArea.append("有新用户p2p链接\r\n");
// user_name_update();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} public void sendFile() {
//文件选择对话框启动,当选择了文件以后给每一个client发送文件
JFileChooser sourceFileChooser = new JFileChooser(".");
sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int status = sourceFileChooser.showOpenDialog(frame);
File sourceFile = new File(sourceFileChooser.getSelectedFile().getPath());
//服务器text area提示
textArea.append("发送文件:" + sourceFile.getName() + "\r\n"); if(sendfor_who==0){
textArea.append("对服务器发送文件!");
}else{
StringTokenizer st = new StringTokenizer(listModel.getElementAt(sendfor_who)+"", "---()");
String user_name = st.nextToken();
String user_state = st.nextToken();
if (user_state.equals("在线")) {
for (int i = clients.size()-1; i >= 0; i--) {
if (clients.get(i).getUser().getName().equals(user_name)) {
SendFileThread sendFile = new SendFileThread(frame, clients.get(i).socket, frame.getTitle(), sourceFileChooser, status);
sendFile.start();
//client端提示
textArea.append("给 "+user_name+" 发送一个文件:" + sourceFile.getName() + "\r\n");
return;
}
}
SendFileThread sendFile = new SendFileThread(frame, socketfor_p2p, frame.getTitle(), sourceFileChooser, status);
sendFile.start();
//client端提示
textArea.append("给 "+user_name+" 发送一个文件:" + sourceFile.getName() + "\r\n");
}else{
JOptionPane.showMessageDialog(frame, "用户不在线,不能发送文件!");
}
} } // 执行发送
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);
if(sendfor_who==0){
sendMessage(frame.getTitle() + "#" + "ALL" + "#" + message);
textField.setText(null);
}else{
StringTokenizer st = new StringTokenizer(listModel.getElementAt(sendfor_who)+"", "---()");
String user_name = st.nextToken();
String user_state = st.nextToken();
if (user_state.equals("在线")) {
for (int i = clients.size()-1; i >= 0; i--) {
if (clients.get(i).getUser().getName().equals(user_name)) {
clients.get(i).writer_ptp.println("对 "+user_name+" 说: "+message+"\r\n");
clients.get(i).writer_ptp.flush();
textArea.append("对 "+user_name+" 说: "+message+"\r\n");
textField.setText(null);
return;
}
}
if (!isConnected_p2p) {
JOptionPane.showMessageDialog(frame, "点对点即将连接!");
sendMessage("P2P#"+user_name);
}else{
P2P_printWriter.println(message);
P2P_printWriter.flush();
textArea.append("对 "+user_name+" 说: "+message+"\r\n");
textField.setText(null);
} }else{
JOptionPane.showMessageDialog(frame, "用户不在线,已存为留言!");
sendMessage("LIXIAN#"+frame.getTitle() + "#" + user_name + "#" + message);
textArea.append("对 "+user_name+" 留言: "+message+"\r\n");
textField.setText(null);
}
}
} public void Login(){
Font font = new Font("宋体", 1, 16); logPanle = new JPanel();
//logPanle.setLayout(new GridLayout(2, 2));
logPanle.setBounds(2, 45, 250, 225);
logPanle.setBackground(Color.lightGray);
logPanle.setLayout(new GridLayout(5, 2, 20, 20)); label_username = new JLabel("用户名:");
label_username.setFont(font);
label_username.setHorizontalAlignment(SwingConstants.CENTER);
logPanle.add(label_username); txt_login_name = new JTextField("name");
txt_login_name.setFont(font);
logPanle.add(txt_login_name); label_password = new JLabel("密 码:");
label_password.setFont(font);
label_password.setHorizontalAlignment(SwingConstants.CENTER);
logPanle.add(label_password); txt_password = new JTextField("");
txt_password.setFont(font);
logPanle.add(txt_password); txt_login_ip = new JTextField("127.0.0.1");
txt_login_ip.setFont(font);
logPanle.add(txt_login_ip); txt_login_port = new JTextField("6666");
txt_login_port.setFont(font);
logPanle.add(txt_login_port); logPanle.add(txt_login_ip);
logPanle.add(txt_login_port); btn_submit = new JButton("登陆");
btn_submit.setFont(font);
btn_submit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int port;
String message_name = txt_login_name.getText().trim();
if (message_name == null || message_name.equals("")) {
JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message_pw = txt_password.getText().trim();
if (message_pw == null || message_pw.equals("")) {
JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
if (isConnected) {
String message1 = txt_login_name.getText().trim();
if (message1 == null || message1.equals("")) {
JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message2 = txt_password.getText().trim();
if (message2 == null || message2.equals("")) {
JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
sendMessage("USERLOGIN#"+message1+"#"+message2+"#"+server_port+"#"+myIP);
return;
}else{
try {
try {
port = Integer.parseInt(txt_login_port.getText().trim());
} catch (NumberFormatException e2) {
throw new Exception("端口号不符合要求!端口为整数!");
}
String hostIp = txt_login_ip.getText().trim();
String name = txt_login_name.getText().trim();
if (name.equals("") || hostIp.equals("")) {
throw new Exception("姓名、服务器IP不能为空!");
}
boolean flag = connectServer(port, hostIp, name);
if (flag == false) {
throw new Exception("与服务器连接失败!");
}
frame.setTitle(name);
listModel.addElement("全部用户");
} catch (Exception exc) {
JOptionPane.showMessageDialog(loginframe, exc.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
return;
}
} sendMessage("USERLOGIN#"+message_name+"#"+message_pw+"#"+server_port+"#"+myIP);
}
});
logPanle.add(btn_submit); btn_zhuce = new JButton("注册");
btn_zhuce.setFont(font);
btn_zhuce.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int port;
String message_name = txt_login_name.getText().trim();
if (message_name == null || message_name.equals("")) {
JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message_pw = txt_password.getText().trim();
if (message_pw == null || message_pw.equals("")) {
JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message_yx = txt_login_forget.getText().trim();
if (message_yx == null || message_yx.equals("")) {
JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
} if (isConnected) {
String message1 = txt_login_name.getText().trim();
if (message1 == null || message1.equals("")) {
JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message2 = txt_password.getText().trim();
if (message2 == null || message2.equals("")) {
JOptionPane.showMessageDialog(logPanle, "密码不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message3 = txt_login_forget.getText().trim();
if (message3 == null || message3.equals("")) {
JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
sendMessage("USERZHUCE#"+message1+"#"+message2+"#"+message3);
return;
}else{
try {
try {
port = Integer.parseInt(txt_login_port.getText().trim());
} catch (NumberFormatException e2) {
throw new Exception("端口号不符合要求!端口为整数!");
}
String hostIp = txt_login_ip.getText().trim();
String name = txt_login_name.getText().trim();
if (name.equals("") || hostIp.equals("")) {
throw new Exception("姓名、服务器IP不能为空!");
}
boolean flag = connectServer(port, hostIp, name);
if (flag == false) {
throw new Exception("与服务器连接失败!");
}
frame.setTitle(name);
listModel.addElement("全部用户");
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
return;
}
} sendMessage("USERZHUCE#"+message_name+"#"+message_pw+"#"+message_yx);
}
});
logPanle.add(btn_zhuce); txt_login_forget = new JTextField("");
txt_login_forget.setFont(font);
logPanle.add(txt_login_forget); btn_forget_pass = new JButton("密码找回");
btn_forget_pass.setFont(font);
btn_forget_pass.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int port; String message_name = txt_login_name.getText().trim();
if (message_name == null || message_name.equals("")) {
JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message_yx = txt_login_forget.getText().trim();
if (message_yx == null || message_yx.equals("")) {
JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message_pw = txt_password.getText().trim();
if (message_pw == null || message_pw.equals("")) {
JOptionPane.showMessageDialog(logPanle, "修改密码不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
} if (isConnected) {
String message1 = txt_login_name.getText().trim();
if (message1 == null || message1.equals("")) {
JOptionPane.showMessageDialog(logPanle, "用户名不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message2 = txt_login_forget.getText().trim();
if (message2 == null || message2.equals("")) {
JOptionPane.showMessageDialog(logPanle, "注册邮箱不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
String message3 = txt_password.getText().trim();
if (message3 == null || message3.equals("")) {
JOptionPane.showMessageDialog(logPanle, "修改密码不能为空!", "错误",
JOptionPane.ERROR_MESSAGE);
return;
}
sendMessage("USERFORGET#"+message1+"#"+message2+"#"+message3);
return;
}else{
try {
try {
port = Integer.parseInt(txt_login_port.getText().trim());
} catch (NumberFormatException e2) {
throw new Exception("端口号不符合要求!端口为整数!");
}
String hostIp = txt_login_ip.getText().trim();
String name = txt_login_name.getText().trim();
if (name.equals("") || hostIp.equals("")) {
throw new Exception("姓名、服务器IP不能为空!");
}
boolean flag = connectServer(port, hostIp, name);
if (flag == false) {
throw new Exception("与服务器连接失败!");
}
frame.setTitle(name);
listModel.addElement("全部用户");
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
return;
}
} sendMessage("USERFORGET#"+message_name+"#"+message_yx+"#"+message_pw);
}
});
logPanle.add(btn_forget_pass); logPanle.setBorder(new TitledBorder("登陆"));
loginframe = new JFrame("登陆窗口");
loginframe.add(logPanle,"Center");
loginframe.setSize(300, 300);
int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
loginframe.setLocation((screen_width - loginframe.getWidth()) / 2,
(screen_height - loginframe.getHeight()) / 2);
loginframe.setVisible(true); // 关闭窗口时事件
loginframe.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (isConnected) {
closeConnection();// 关闭连接
closeServer();//关闭服务程序
}
System.exit(0);// 退出程序
}
});
} // 构造方法
public Client() throws BindException { serverStart(0); SelecTry selectIndex=new SelecTry(); textArea = new JTextArea();
textArea.setEditable(false);
textArea.setForeground(Color.blue);
textField = new JTextField();
txt_port = new JTextField("6666");
txt_hostIp = new JTextField("127.0.0.1");
txt_name = new JTextField("姓名");
btn_start = new JButton("连接");
btn_stop = new JButton("断开");
btn_send = new JButton("发送");
btn_send_file = new JButton("文件");
listModel = new DefaultListModel();
userList = new JList(listModel);
//listModel.addElement("全部用户");
userList.addListSelectionListener(selectIndex);
northPanel = new JPanel();
northPanel.setLayout(new GridLayout(1, 7));
northPanel.add(new JLabel(" 端口"));
northPanel.add(txt_port);
northPanel.add(new JLabel(" 服务器IP"));
northPanel.add(txt_hostIp);
northPanel.add(new JLabel(" 姓名"));
northPanel.add(txt_name);
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());
sendPanel = new JPanel(new BorderLayout());
southPanel.setBorder(new TitledBorder("写消息"));
southPanel.add(textField, "Center");
sendPanel.add(btn_send, BorderLayout.NORTH);
sendPanel.add(btn_send_file, BorderLayout.SOUTH);
southPanel.add(sendPanel, "East"); centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScroll,
rightScroll);
centerSplit.setDividerLocation(150); frame = new JFrame("客户机");
// 更改JFrame的图标:
//frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.getResource("qq.png")));
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(false); // 写消息的文本框中按回车键时事件
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
send();
}
}); // 单击发送按钮时事件
btn_send.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send();
}
}); //单机文件按钮时事件
btn_send_file.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
sendFile();
}
}); // 单击连接按钮时事件
// btn_start.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// int port;
// if (isConnected) {
// JOptionPane.showMessageDialog(frame, "已处于连接上状态,不要重复连接!",
// "错误", JOptionPane.ERROR_MESSAGE);
// return;
// }
// try {
// try {
// port = Integer.parseInt(txt_port.getText().trim());
// } catch (NumberFormatException e2) {
// throw new Exception("端口号不符合要求!端口为整数!");
// }
// String hostIp = txt_hostIp.getText().trim();
// String name = txt_name.getText().trim();
// if (name.equals("") || hostIp.equals("")) {
// throw new Exception("姓名、服务器IP不能为空!");
// }
// boolean flag = connectServer(port, hostIp, name);
// if (flag == false) {
// throw new Exception("与服务器连接失败!");
// }
// listModel.addElement("全部用户");
// frame.setTitle(name);
// JOptionPane.showMessageDialog(frame, "成功连接!");
// } catch (Exception exc) {
// JOptionPane.showMessageDialog(frame, exc.getMessage(),
// "错误", JOptionPane.ERROR_MESSAGE);
// }
// }
// }); // 单击断开按钮时事件
btn_stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!isConnected) {
JOptionPane.showMessageDialog(frame, "已处于断开状态,不要重复断开!",
"错误", JOptionPane.ERROR_MESSAGE);
return;
}
try {
boolean flag = closeConnection();// 断开连接
closeServer();
if (flag == false) {
throw new Exception("断开连接发生异常!");
}
JOptionPane.showMessageDialog(frame, "成功断开!");
frame.setVisible(false);
textArea.setText("");
loginframe.setVisible(true);
listModel.removeAllElements();
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
}
}
}); // 关闭窗口时事件
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (isConnected) {
closeConnection();// 关闭连接
closeServer();//关闭服务程序
}
System.exit(0);// 退出程序
}
});
Login();
} /**
* 连接服务器
*
* @param port
* @param hostIp
* @param name
*/
public boolean connectServer(int port, String hostIp, String name) {
// 连接服务器
try {
socket = new Socket(hostIp, port);// 根据端口号和服务器ip建立连接
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
// 发送客户端用户基本信息(用户名和ip地址)
sendMessage(name + "#" + socket.getLocalAddress().toString());
// 开启接收消息的线程
messageThread = new MessageThread(reader, textArea);
messageThread.start();
isConnected = true;// 已经连接上了
return true;
} catch (Exception e) {
textArea.append("与端口号为:" + port + " IP地址为:" + hostIp
+ " 的服务器连接失败!" + "\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;
listModel.removeAllElements();
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();// 被动的关闭连接
JOptionPane.showMessageDialog(frame, "服务器已关闭!", "错误",
JOptionPane.ERROR_MESSAGE);
frame.setVisible(false);
textArea.setText("");
loginframe.setVisible(true);
return;// 结束线程
} else if (command.equals("ADD")) {// 有用户上线更新在线列表
String username = "";
String userIp = "";
if ((username = stringTokenizer.nextToken()) != null
&& (userIp = stringTokenizer.nextToken()) != null) {
User user = new User(username, userIp);
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")) {// 加载在线用户列表
listModel.removeAllElements();
listModel.addElement("全部用户");
StringTokenizer strToken ;
String user ;// 命令
int size = Integer
.parseInt(stringTokenizer.nextToken());
String username = null;
String userIp = null;
for (int i = 0; i < size-1; i++) {
username = stringTokenizer.nextToken();
strToken = new StringTokenizer(username, "---()");
if (strToken.nextToken().equals(frame.getTitle())) {
continue;
}else{
listModel.addElement(username);
}
//userIp = stringTokenizer.nextToken();
//User user = new User(username, userIp);
//onLineUsers.put(username, user);
}
} else if (command.equals("MAX")) {// 人数已达上限
textArea.append(stringTokenizer.nextToken()
+ stringTokenizer.nextToken() + "\r\n");
closeCon();// 被动的关闭连接
JOptionPane.showMessageDialog(frame, "服务器缓冲区已满!", "错误",
JOptionPane.ERROR_MESSAGE);
return;// 结束线程
} else if(command.equals("FILE")){
int portNumber = Integer.parseInt(stringTokenizer.nextToken());
String fileName = stringTokenizer.nextToken();
long fileSize = Long.parseLong(stringTokenizer.nextToken());
String ip = stringTokenizer.nextToken();
String Nickname = stringTokenizer.nextToken();
ReceiveFileThread receiveFile = new ReceiveFileThread(textArea,frame,ip, portNumber, fileName, fileSize, Nickname);
receiveFile.start();
textArea.append("从"+Nickname+"接受文件:"+fileName+",大小为:"+fileSize
+"ip:"+ip+"port:"+portNumber+"\r\n");
}else if(command.equals("USERLOGIN")){
String st = stringTokenizer.nextToken();
if(st.equals("OK")){
JOptionPane.showMessageDialog(loginframe, "登陆成功!" );
loginframe.setVisible(false);
txt_name.setText(txt_login_name.getText());
frame.setVisible(true);
int count = stringTokenizer.countTokens();
while(true){
if(count==0){
break;
}
textArea.append(stringTokenizer.nextToken()+" 对你留言 ,");
textArea.append("时间: "+stringTokenizer.nextToken()+"\r\n ");
textArea.append("留言内容: "+stringTokenizer.nextToken()+"\r\n");
count-=3;
} }else if(st.equals("ALREADY")){
JOptionPane.showMessageDialog(loginframe, "账号已登陆!" );
}else{
JOptionPane.showMessageDialog(loginframe, "登陆失败!" );
}
}else if(command.equals("USERZHUCE")){
String st = stringTokenizer.nextToken();
if(st.equals("OK")){
JOptionPane.showMessageDialog(loginframe, "注册成功!" ); }else if(st.equals("exict")){
JOptionPane.showMessageDialog(loginframe, "用户名已存在!" );
}else{
JOptionPane.showMessageDialog(loginframe, "注册失败!" );
}
}else if(command.equals("USERFORGET")){
String st = stringTokenizer.nextToken();
if(st.equals("OK")){
JOptionPane.showMessageDialog(loginframe, "修改密码成功!" ); }else if(st.equals("YOUXIANG_WRONG")){
JOptionPane.showMessageDialog(loginframe, "邮箱错误!" );
}else if(st.equals("NAME_NO_exict")){
JOptionPane.showMessageDialog(loginframe, "用户不存在!" );
}else{
JOptionPane.showMessageDialog(loginframe, "找回密码失败!" );
}
} else if (command.equals("P2P")) {
String st = stringTokenizer.nextToken();
if(st.equals("OK")){
String username = stringTokenizer.nextToken();
int serverPort = Integer.parseInt(stringTokenizer.nextToken());
String ip = stringTokenizer.nextToken();
boolean cn = connectServer_p2p(serverPort,ip,username);
if (cn) {
JOptionPane.showMessageDialog(frame, "与"+username+"的连接成功,端口号为:"+serverPort+"IP:"+ip );
P2P_printWriter.println(frame.getTitle()+"#"+myIP);
P2P_printWriter.flush(); String msg = textField.getText().trim();
P2P_printWriter.println(msg);
P2P_printWriter.flush(); textArea.append("对 "+username+" 说: "+msg+"\r\n"); textField.setText(null);
} }else{
String username = stringTokenizer.nextToken();
JOptionPane.showMessageDialog(frame, "与"+username+"的连接失败!");
}
} else {// 普通消息
textArea.append(message + "\r\n");
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
 package com.company;

 import javax.swing.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket; public class SendFileThread extends Thread {
private Socket clientSocket;
private String name;
JFileChooser sourceFileChooser;
int status;
JFrame JFrame; public SendFileThread(JFrame frame, Socket socket, String name, JFileChooser sourceFileChooser, int status) {
this.clientSocket = socket;
this.name = name;
this.sourceFileChooser = sourceFileChooser;
this.status = status;
this.JFrame = frame;
} public void run() {
// JFileChooser sourceFileChooser = new JFileChooser(".");
// sourceFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
// int status = sourceFileChooser.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION) {
File sourceFile = new File(sourceFileChooser.getSelectedFile().getPath());
String sourceFilePath = sourceFile.getAbsolutePath();
String fileName = sourceFile.getName();
//System.out.println(sourceFilePath+"\\"+fileName);
try {
PrintWriter sendToClient = new PrintWriter(clientSocket.getOutputStream());
BufferedReader getFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
ServerSocket fileSenderSocket = null;
try {
fileSenderSocket = new ServerSocket(0);
} catch (IOException ex1) {
JOptionPane.showMessageDialog(JFrame, "无法分配端口以发送此文件!", "错误", JOptionPane.ERROR_MESSAGE);
}
sendToClient.println("FILE#" + fileSenderSocket.getLocalPort() + "#" + fileName + "#"
+ String.valueOf(sourceFile.length()) + "#" + clientSocket.getLocalAddress() + "#" + name);
sendToClient.flush();
//System.out.println("Sender: "+fileSenderSocket.getLocalSocketAddress());
Socket fileReceiverSocket = fileSenderSocket.accept(); BufferedReader getFromReceiver = null;
PrintWriter sendToReceiver = null;
try {
getFromReceiver = new BufferedReader(new InputStreamReader(fileReceiverSocket.getInputStream()));
sendToReceiver = new PrintWriter(fileReceiverSocket.getOutputStream());
} catch (IOException ex) {
} finally {
}
String judge = getFromReceiver.readLine();
if (judge.equals("accepted")) {
DataOutputStream sendFileToReceiver = new DataOutputStream(new BufferedOutputStream(fileReceiverSocket.getOutputStream()));
ProgressMonitorInputStream monitor;
FileInputStream sendFileStream = null;
try {
sendFileStream = new FileInputStream(sourceFile);
} catch (FileNotFoundException ex) {
sendToReceiver.flush();
sendFileToReceiver.writeByte(0);
sendFileToReceiver.flush();
return;
}
monitor = new ProgressMonitorInputStream(JFrame, "正在发送: " + fileName, sendFileStream);
ProgressMonitor progressMonitor = monitor.getProgressMonitor(); int read_unit = 500;
long fileSize = monitor.available();
int readed = 0;
byte[] data = new byte[read_unit];
try {
sendFileToReceiver.writeByte(1);
sendFileToReceiver.flush();
while (monitor.available() > 0) {
int in = monitor.read(data);
readed += in;
float process = (float) readed / fileSize * 100;
progressMonitor.setNote(process + " % 完成");
if (in > 0) {
sendFileToReceiver.write(data, 0, in);
}
}
sendFileToReceiver.flush();
} catch (IOException e) {
JOptionPane.showMessageDialog(JFrame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE);
} finally {
if (sendFileStream != null)
try {
sendFileStream.close();
monitor.close();
} catch (IOException e) {
}
}
try {
fileReceiverSocket.close();
} catch (IOException ex1) {
}
} else if (judge.equals("refused")) {
JOptionPane.showMessageDialog(JFrame, "对方拒绝接受文件 " + fileName, "错误!", JOptionPane.INFORMATION_MESSAGE);
} } catch (IOException ex) {
} finally {
}
}
}
}
 package com.company;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket; import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.ProgressMonitor;
import javax.swing.ProgressMonitorInputStream; public class ReceiveFileThread extends Thread {
private String fileSenderIPAddress;
private int fileSenderPortNumber;
private String fileName;
private long fileSize;
private String otherNickname;
JFrame frame;
JTextArea textArea; public ReceiveFileThread(JTextArea textArea,JFrame frame,String ip, int port_number, String file_name, long file_size, String other_nickname) {
this.fileSenderIPAddress = ip;
this.fileSenderPortNumber = port_number;
this.fileName = file_name;
this.fileSize = file_size;
this.otherNickname = other_nickname;
this.frame = frame;
this.textArea = textArea;
} public void run() {
Socket fileSenderSocket = null;
try {
fileSenderSocket = new Socket(fileSenderIPAddress, fileSenderPortNumber);
}
catch(IOException ex) {
JOptionPane.showMessageDialog(frame, "无法连接到服务器接收文件!", "错误", JOptionPane.ERROR_MESSAGE);
}
finally {
}
DataInputStream getFromSender = null;
DataOutputStream sendToSender = null;
try {
getFromSender = new DataInputStream(new BufferedInputStream(fileSenderSocket.getInputStream()));
sendToSender = new DataOutputStream(new BufferedOutputStream(fileSenderSocket.getOutputStream()));
BufferedReader getInfoFromSender =new BufferedReader(new InputStreamReader(getFromSender)); int permit = JOptionPane.showConfirmDialog(frame, "接受文件:"+fileName+" 从 "+otherNickname+"?", "文件传输请求:", JOptionPane.YES_NO_OPTION);
if(permit == JOptionPane.YES_OPTION) {
sendToSender.writeBytes("accepted\n");
sendToSender.flush(); JFileChooser destinationFileChooser = new JFileChooser(".");
destinationFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int status = destinationFileChooser.showSaveDialog(frame);
File destinationPath = null;
if (status == JFileChooser.APPROVE_OPTION) {
destinationPath = new File(destinationFileChooser.getSelectedFile().getPath());
//String destinationFile = destinationPath.getAbsolutePath()+"\\"+fileName;
//System.out.println(destinationFilePath);
}
try {
byte judge = getFromSender.readByte();
if (judge > 0) {
File savedFile = new File(destinationPath.getAbsolutePath()+"\\"+fileName);
FileOutputStream saveFileStream = new FileOutputStream(savedFile);
DataOutputStream fileOutput = new DataOutputStream(saveFileStream);
ProgressMonitorInputStream monitor = new ProgressMonitorInputStream(frame, "接受文件: "+fileName, getFromSender);
//ProgressMonitor progressMonitor = new ProgressMonitor(null, "Receiving "+fileName, "", 0, (int)fileSize);
ProgressMonitor progressMonitor = monitor.getProgressMonitor();
progressMonitor.setMaximum((int)fileSize); int read_unit = 500;
int readed = 0;
float process = 0;
try {
while (true) {
byte[] data = new byte[read_unit];
int in = monitor.read(data);
readed += in;
process = (float) readed / fileSize * 100;
progressMonitor.setNote(process+" % 完成");
progressMonitor.setProgress(readed);
if (in <= 0) {
break;
}
fileOutput.write(data,0,in);
} fileOutput.flush();
if(savedFile.length() < fileSize) {
JOptionPane.showMessageDialog(frame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE);
}
textArea.append("接受文件:"+fileName+" 保存地址:"+destinationPath+"\r\n");
}
catch(IOException e){
JOptionPane.showMessageDialog(frame, "传输中断!", "错误", JOptionPane.ERROR_MESSAGE);
}
finally {
try {
fileOutput.close();
saveFileStream.close();
progressMonitor.close();
}
catch(IOException e){
}
}
}
else {
JOptionPane.showMessageDialog(frame, "源文件没有找到!", "错误", JOptionPane.ERROR_MESSAGE);
}
}
catch(IOException e){
}
finally {
fileSenderSocket.close();
}
}
else if(permit == JOptionPane.NO_OPTION) {
sendToSender.writeBytes("refused\n");
sendToSender.flush();
}
}
catch(IOException ex) {
}
finally {
}
//System.out.println("Receiver: "+fileReceiverSocket.getRemoteSocketAddress());
} }
 package com.company;

 //用户信息类
public class User{
private String name;
private String ip;
private int state; public User(String name, String ip) {
this.name = name;
this.ip = ip;
} 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;
} public int getState() {
return state;
} public void setState(int state){
this.state=state;
}
}

是一次实验课的第一次实验,可能还有bug,请理解!

后期会更新。