实现效果图:

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机制,重构线程,将单独的登录和注册线程合并的更多相关文章

  1. java在线聊天项目1.2版 ——开启多个客户端,分别实现数据库注册和登录功能后,成功登陆则登录框消失,好友列表窗出现

    登录框消失语句 dispose(); 好友列表窗出现 使用new FriendsFrame(phone,s); 登陆对话框代码修改如下: package com.swift.frame; import ...

  2. java在线聊天项目0.9版 实现把服务端接收到的信息返回给每一个客户端窗口中显示功能之客户端接收

    客户端要不断接收服务端发来的信息 与服务端不断接收客户端发来信息相同,使用线程的方法,在线程中循环接收 客户端修改后代码如下: package com.swift; import java.awt.B ...

  3. java在线聊天项目0.7版 连接多个客户端问题,开启多个客户端后服务器端只接收到一个 对各种异常的补充处理

    问题的原因是 while(connected) { String str=dis.readUTF(); System.out.println(str); } 不断循环执行,一直在死循环获取socket ...

  4. java在线聊天项目1.0版 异常处理——开启多个客户端,关闭一个客户端后,在其他客户端中再发出信息会出现异常的处理

    异常一 只开启一个客户端,输入信息后关闭,客户端出现如下异常 根据异常说明 ChatClientFrame客户端117行 提示原因是Socket关闭 分析原因 客户端代码 while (connect ...

  5. java在线聊天项目1.3版 ——设计好友列表框功能

    设计好友列表框功能,思路—— 1.当客户端成功登陆后,则客户端把成功登陆信息发送给服务端, 2.由服务端将接收到来自各个成功登陆的客户端的用户信息添加进好友列表, 3.每当有成功登陆的用户就向各个客户 ...

  6. java在线聊天项目0.6版 解决客户端关闭后异常问题 dis.readUTF()循环读取已关闭的socket

    服务端对try catch finally重新进行了定义,当发生异常,主动提示,或关闭出现异常的socket 服务器端代码修改如下: package com.swift; import java.io ...

  7. java在线聊天项目0.5版 解决客户端向服务器端发送信息时只能发送一次问题 OutputStreamWriter DataOutputStream socket.getOutputStream()

    没有解决问题之前客户端代码: package com.swift; import java.awt.BorderLayout; import java.awt.Color; import java.a ...

  8. java在线聊天项目0.8版 实现把服务端接收到的信息返回给每一个客户端窗口中显示功能

    迭代器的方式会产生锁定 服务器端增加发送给每个客户端已收到信息的功能 所以当获取到一个socket,并打开它的线程进行循环接收客户端发来信息时,我们把这个内部类的线程Client保存到集合List&l ...

  9. java在线聊天项目1.3版设计好友列表框功能补充,因只要用户登录就发送一串新列表,导致不同客户端好友列表不同问题

    解决完毕后效果图: 好友列表Vector添加的时候进行判断,如果有相同的则不添加 int flag=0; for (int i = 0; i < names.size(); i++) { if ...

随机推荐

  1. SqlServer 分页批按时间排序

    sql server 分页按时间排序 select * from (select<include refid="Base_Column_List"/>, ROW_NUM ...

  2. js中的同步和异步的个人理解(转)

    你应该知道,javascript语言是一门“单线程”的语言,不像java语言,类继承Thread再来个thread.start就可以开辟一个线程,所以,javascript就像一条流水线,仅仅是一条流 ...

  3. Gym - 101810D ACM International Collegiate Programming Contest (2018)

    bryce1010模板 http://codeforces.com/gym/101810 #include <bits/stdc++.h> using namespace std; #de ...

  4. Technocup 2017 - Elimination Round 1 (Unofficially Open for Everyone, Rated for Div. 2) D

    The organizers of a programming contest have decided to present t-shirts to participants. There are ...

  5. [POI2011]Plot

    https://szkopul.edu.pl/problemset/problem/mzrTn1kzVBOAwVYn55LUeAai/site/?key=statement 既卡常又卡精度...真的A ...

  6. 关于foreach的一个BUG

    foreach用起来比for更方便,但是foreach隐藏的操作,可能带来更多未知的BUG,今天就遇到一个问题.编程环境VS2010 //使用foreach遍历,其中未改变item的值,但是使用了匿名 ...

  7. Mysql5.7免编译版自动安装脚本

    一:readme: .此脚本仅仅适合于5.7免面编译安装版本. .安装是需自己选择mysql软件安装包:例如mysql--linux-glibc2.-x86_64.-linux-glibc2.-x86 ...

  8. 一些API

    /** * Goto the specified frame index, and pause at this index. * @param startIndex The animation wil ...

  9. 《javascript设计模式》笔记之第五章:单体模式

    一:单体的基本结构: 最简单的单体,实际就是一个对象字面量: var Singleton = { attribute1: true, attribute2, method1: function() { ...

  10. kafka系列二:多节点分布式集群搭建

    上一篇分享了单节点伪分布式集群搭建方法,本篇来分享一下多节点分布式集群搭建方法.多节点分布式集群结构如下图所示: 为了方便查阅,本篇将和上一篇一样从零开始一步一步进行集群搭建. 一.安装Jdk 具体安 ...