java在线聊天项目1.1版 ——开启多个客户端,分别实现注册和登录功能,使用客户端与服务端信息request机制,重构线程,将单独的登录和注册线程合并
实现效果图:

eclipse项目中初步整合之前的各个客户端和服务端的窗口与工具类,效果如下图:

已将注册服务器线程RegServer功能放到LoginServer中,使用客户端与服务端的request请求机制,根据请求是注册还是登录,分别进行相应response,客户端根据相应内容判断下一步操作。
发送信息的模式还较为原始,没有使用json方法,但gson包已经导入,支持发送键值对的字符串,及自动解析。
登录对话框LoginDialog类代码如下:
package com.swift.frame; import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket; import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.TitledBorder; import com.google.gson.Gson;
import com.swift.util.Center; public class LoginDialog extends JDialog { private JPasswordField passwordField_2;
private JPasswordField passwordField_1;
private JTextField textField_2;
private JTextField textField;
String request = null;
String response = null; Socket s;
DataOutputStream dos;
DataInputStream dis; public static void main(String args[]) {
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true); try {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
} catch (InstantiationException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (UnsupportedLookAndFeelException e1) {
e1.printStackTrace();
} EventQueue.invokeLater(new Runnable() {
public void run() {
try {
LoginDialog dialog = new LoginDialog();
dialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
} public LoginDialog() {
super();
setResizable(false);
setTitle("在线聊天登录框");
getContentPane().setLayout(null);
setBounds(100, 100, 427, 301);// 注册时高度为578,不注册是301 // 设置窗口居中
this.setLocation(Center.getPoint(this.getSize())); final JTextField textField_1 = new JTextField();
textField_1.setBounds(148, 90, 192, 42);
getContentPane().add(textField_1); final JLabel label = new JLabel();
label.setText("帐 号");
label.setBounds(76, 102, 66, 18);
getContentPane().add(label); final JLabel label_1 = new JLabel();
label_1.setText("密 码");
label_1.setBounds(76, 167, 66, 18);
getContentPane().add(label_1); final JPasswordField passwordField = new JPasswordField();
passwordField.setBounds(148, 155, 192, 42);
getContentPane().add(passwordField); final JButton button_1 = new JButton();
button_1.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) { String phone = new String(textField_1.getText()).trim();
String password = new String(passwordField.getPassword()).trim();
if (!phone.equals("") && !password.equals("")) {
try {
request = "login";
dos.writeUTF(request);
response = dis.readUTF();
if (response.equals("login")) {
dos.writeUTF(phone);
dos.writeUTF(password);
String flag=dis.readUTF();
if(flag.equals("success")) {
javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "登录成功");
}else if(flag.equals("fail")) {
javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "登录失败");
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
} else {
javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "用户名密码必须填写...");
return;
}
}
});
button_1.setText("登录");
button_1.setBounds(230, 222, 106, 36);
getContentPane().add(button_1); final JButton button = new JButton();
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (LoginDialog.this.getHeight() == 301) {
LoginDialog.this.setSize(427, 578);
} else {
LoginDialog.this.setSize(427, 301);
}
// 设置窗口不断居中
LoginDialog.this.setLocation(Center.getPoint(LoginDialog.this.getSize()));
}
});
button.setText("注册");
button.setBounds(76, 222, 106, 36);
getContentPane().add(button); final JPanel panel = new JPanel();
panel.setLayout(null);
panel.setBorder(new TitledBorder(null, "注册用户", TitledBorder.DEFAULT_JUSTIFICATION,
TitledBorder.DEFAULT_POSITION, null, null));
panel.setBounds(10, 278, 401, 226);
getContentPane().add(panel); final JLabel label_2 = new JLabel();
label_2.setBounds(44, 41, 65, 18);
label_2.setText("手机号:");
panel.add(label_2); textField = new JTextField();
textField.setBounds(115, 35, 225, 30);
panel.add(textField); final JButton button_2 = new JButton();
button_2.setText("发送验证");
button_2.setBounds(243, 75, 97, 30);
panel.add(button_2); textField_2 = new JTextField();
textField_2.setBounds(115, 104, 95, 30);
panel.add(textField_2); final JLabel label_3 = new JLabel();
label_3.setText("验证码:");
label_3.setBounds(44, 110, 65, 18);
panel.add(label_3); passwordField_1 = new JPasswordField();
passwordField_1.setBounds(115, 143, 231, 30);
panel.add(passwordField_1); passwordField_2 = new JPasswordField();
passwordField_2.setBounds(115, 175, 231, 30);
panel.add(passwordField_2); final JLabel label_4 = new JLabel();
label_4.setText("密 码:");
label_4.setBounds(44, 149, 65, 18);
panel.add(label_4); final JLabel label_5 = new JLabel();
label_5.setText("验证密码:");
label_5.setBounds(44, 181, 65, 18);
panel.add(label_5); final JButton button_3 = new JButton();
button_3.setBounds(47, 510, 97, 30);
getContentPane().add(button_3);
button_3.setText("放弃"); final JButton button_4 = new JButton();
button_4.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) { String phone = textField.getText();
String password = null;
String str1 = new String(passwordField_1.getPassword()).trim();
String str2 = new String(passwordField_2.getPassword()).trim();
if (!phone.equals("") && !str1.equals("") && !str2.equals("")) {
if (str1.equals(str2)) {
password = new String(passwordField_2.getPassword()).trim();
try {
request = "reg";
dos.writeUTF(request);
String response = dis.readUTF();
if (response.equals("reg")) {
dos.writeUTF(phone);
dos.writeUTF(password);
}
javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "注册成功...");
} catch (IOException e1) {
e1.printStackTrace();
}
} else {
javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "输入密码不一致...");
System.out.println("输入密码不一致...");
passwordField_1.setText("");
passwordField_2.setText("");
} } else {
javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "用户名密码必须填写...");
return;
}
}
}); button_4.setBounds(262, 510, 97, 30);
getContentPane().add(button_4);
button_4.setText("注册用户"); connect();
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
disconnect();
}
});
} public void connect() {
try {
s = new Socket("127.0.0.1", 8888);
System.out.println("一个客户端登陆中....!");
dos = new DataOutputStream(s.getOutputStream());
dis = new DataInputStream(s.getInputStream()); } catch (ConnectException e) {
System.out.println("服务端异常.........");
System.out.println("请确认服务端是否开启.........");
} catch (IOException e) {
e.printStackTrace();
}
} public void disconnect() {
try {
if (dos != null)
dos.close();
if (s != null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
登录与注册的服务端代 LoginServer类码如下:
package com.swift.server; import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException; import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.swift.frame.LoginDialog;
import com.swift.jdbc.DBAdd;
import com.swift.jdbc.DBLogin;
import com.swift.other.User; public class LoginServer { boolean started = false;
ServerSocket ss = null;
Socket s = null;
String request = null;
String response = null; public static void main(String[] args) {
new LoginServer().fun();
} private void fun() {
try {
ss = new ServerSocket(8888);
started = true;
} catch (BindException e) {
System.out.println("端口使用中......");
} catch (IOException e1) {
e1.printStackTrace();
}
try {
while (started) {
s = ss.accept();
System.out.println("a client connected success");
Client c = new Client(s);
new Thread(c).start();
}
} catch (EOFException e) {
System.out.println("client has closed.");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} class Client implements Runnable { private Socket s;
private DataInputStream dis;
private DataOutputStream dos;
private boolean connected = false; public Client(Socket s) {
this.s = s;
try {
this.dis = new DataInputStream(s.getInputStream());
this.dos = new DataOutputStream(s.getOutputStream());
connected = true;
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void run() {
try {
while (connected) {
request = dis.readUTF();
response = request;
dos.writeUTF(response);
if (request.equals("login")) { String phone = dis.readUTF();
String password = dis.readUTF();
System.out.println(phone);
System.out.println(password); User user = new User(phone, password);
boolean login = DBLogin.login(user);
if (login) {
dos.writeUTF("success");
}else {
dos.writeUTF("fail");
} } else if (request.equals("reg")) {
String phone = dis.readUTF();
String password = dis.readUTF();
System.out.println(phone);
System.out.println(password); User user = new User(phone, password);
DBAdd.add(user);
}
}
} catch (SocketException e) {
System.out.println("一个登陆窗已经关闭....");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (s != null) {
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} }
}
连接数据库工具类DBUtil类代码:
package com.swift.jdbc; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class DBUtil { public static Connection getConn() {
Connection conn=null;
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
String url="jdbc:mysql://localhost:3306/sw_database";
String user="root";
String password="root";
conn=DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
} public static void closeAll(Connection conn,PreparedStatement ps,ResultSet rs) { if(conn!=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
添加到数据库的类DBAdd代码:
package com.swift.jdbc; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; import com.swift.other.User; public class DBAdd { public static void add(User user) { String phone = user.getUsername();
String password = user.getPassword(); Connection conn = DBUtil.getConn();
PreparedStatement ps=null;
try {
ps = conn.prepareStatement("insert into sw_user(username,password) values(?,?)");
ps.setString(1, phone);
ps.setString(2, password);
int count = ps.executeUpdate();
if (count == 1) {
System.out.println("用户添加成功");
} else {
System.out.println("用户添加失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.closeAll(conn, ps, null);
} } }
登录时查询数据库DBLogin类代码:
package com.swift.jdbc; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import com.swift.other.User; public class DBLogin { public static boolean login(User user) { Connection conn=DBUtil.getConn();
PreparedStatement ps=null;
ResultSet rs=null;
try {
ps=conn.prepareStatement("select * from sw_user where username=? and password=?");
ps.setString(1, user.getUsername());
ps.setString(2, user.getPassword());
rs=ps.executeQuery();
if(rs.next()) {
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DBUtil.closeAll(conn, ps, rs);
return false;
}
}
两个辅助类User类和居中类Center
package com.swift.other;
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public User() {
super();
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
}
Center类:
package com.swift.util; import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit; public class Center {
public static Point getPoint(int width,int height) {
Toolkit toolkit=Toolkit.getDefaultToolkit();//应该是单例
int screenW=toolkit.getScreenSize().width;
int screenH=toolkit.getScreenSize().height;
int x=(screenW-width)/2;
int y=(screenH-height)/2;
Point p=new Point(x,y);
return p;
}
//函数的重载,参数是包装类尺寸——Dimension
public static Point getPoint(Dimension d) {
Point p=getPoint(d.width,d.height);
return p;
}
}
java在线聊天项目1.1版 ——开启多个客户端,分别实现注册和登录功能,使用客户端与服务端信息request机制,重构线程,将单独的登录和注册线程合并的更多相关文章
- java在线聊天项目1.2版 ——开启多个客户端,分别实现数据库注册和登录功能后,成功登陆则登录框消失,好友列表窗出现
登录框消失语句 dispose(); 好友列表窗出现 使用new FriendsFrame(phone,s); 登陆对话框代码修改如下: package com.swift.frame; import ...
- java在线聊天项目0.9版 实现把服务端接收到的信息返回给每一个客户端窗口中显示功能之客户端接收
客户端要不断接收服务端发来的信息 与服务端不断接收客户端发来信息相同,使用线程的方法,在线程中循环接收 客户端修改后代码如下: package com.swift; import java.awt.B ...
- java在线聊天项目0.7版 连接多个客户端问题,开启多个客户端后服务器端只接收到一个 对各种异常的补充处理
问题的原因是 while(connected) { String str=dis.readUTF(); System.out.println(str); } 不断循环执行,一直在死循环获取socket ...
- java在线聊天项目1.0版 异常处理——开启多个客户端,关闭一个客户端后,在其他客户端中再发出信息会出现异常的处理
异常一 只开启一个客户端,输入信息后关闭,客户端出现如下异常 根据异常说明 ChatClientFrame客户端117行 提示原因是Socket关闭 分析原因 客户端代码 while (connect ...
- java在线聊天项目1.3版 ——设计好友列表框功能
设计好友列表框功能,思路—— 1.当客户端成功登陆后,则客户端把成功登陆信息发送给服务端, 2.由服务端将接收到来自各个成功登陆的客户端的用户信息添加进好友列表, 3.每当有成功登陆的用户就向各个客户 ...
- java在线聊天项目0.6版 解决客户端关闭后异常问题 dis.readUTF()循环读取已关闭的socket
服务端对try catch finally重新进行了定义,当发生异常,主动提示,或关闭出现异常的socket 服务器端代码修改如下: package com.swift; import java.io ...
- java在线聊天项目0.5版 解决客户端向服务器端发送信息时只能发送一次问题 OutputStreamWriter DataOutputStream socket.getOutputStream()
没有解决问题之前客户端代码: package com.swift; import java.awt.BorderLayout; import java.awt.Color; import java.a ...
- java在线聊天项目0.8版 实现把服务端接收到的信息返回给每一个客户端窗口中显示功能
迭代器的方式会产生锁定 服务器端增加发送给每个客户端已收到信息的功能 所以当获取到一个socket,并打开它的线程进行循环接收客户端发来信息时,我们把这个内部类的线程Client保存到集合List&l ...
- java在线聊天项目1.3版设计好友列表框功能补充,因只要用户登录就发送一串新列表,导致不同客户端好友列表不同问题
解决完毕后效果图: 好友列表Vector添加的时候进行判断,如果有相同的则不添加 int flag=0; for (int i = 0; i < names.size(); i++) { if ...
随机推荐
- HDU5908【模拟】
思路: 找到约数k,然后算一下1-k区间里的数的个数. 中间交换一下就好了,然后把后面每个区间里的数减减,然后再判断一下满足不满足= = #include <bits/stdc++.h> ...
- ADT版本查看,This Android SDK requires Andr...ate ADT to the latest问题
ADT版本查看 Help->About ADT This Android SDK requires Andr...ate ADT to the latest问题 这样的问题很好解决,一个升级AD ...
- bzoj 4032: [HEOI2015]最短不公共子串【dp+SAM】
第一.二问: 就是最小的最长公共长度+1,设f[i][j]为a匹配到i,b匹配到j,第一问的转移是f[i][j]=(a[i]==b[j]?f[i-1][j-1]+1:0),第二问的转移是f[i][j] ...
- Promise对象深入理解
目录 基本用法 返回另一个 Promise 实例 Promise.prototypeof.then Promise.prototype.catch Promise.prototype.finally ...
- SpringBoot整合Memached
一.Memached介绍 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站 ...
- 最长上升序列(Lis)
Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence ...
- slice方法可以将“类似数组的对象”变成真正的数组 (遇到时候再研究一次)
典型的“类似数组的对象”是函数的arguments对象,以及大多数 DOM 元素集,还有字符串. // arguments对象 function args() { return arguments } ...
- JSP && Servlet | 错误统一处理
对404错误和500错误处理: 在WebContent文件下新建404.jsp 和 500.jsp 显示错误时弹出的信息 <%@ page language="java" c ...
- 51nod 2133 排队接水
Bryce1010模板 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=2133 #include <bits/std ...
- 洛谷 P2662 牛场围栏
做法是这样的: 首先暴力把所有可能的边长搞出来..(当然<=0的不要) 排序边长+去重, 当且仅当可行边长里面有1时,任何长度都能取到,输出-1 当且仅当所有可行边长的gcd大于1时,不能取到的 ...