📄 server.java
字号:
import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Server {
private JFrame f;
private JTextField portF;
private int port;
private boolean isRunning = false;
private JLabel personsLab;
private Connection con;
/*封装了与各用户的连接!*/
private HashMap<String,MySocket> user;
private Socket currentSocket;
private HashMap<String,ClientInfo> userInfo;
private ClientInfo currentUserInfo;
/**
* 服务器和当前服务的客户的通信
*/
private ObjectInputStream input;
private ObjectOutputStream output;
public Server(){
init();
buildGUI();
}
private void init(){
/**SQL server 2000
QQClient数据库,建立Client_Tab
密码位cat,测试时候需要更改
*/
if(this.loadDBDriver("QQClient", "sa", "cat")){
this.user = new HashMap<String, MySocket>();
this.userInfo = new HashMap<String,ClientInfo>();
}else{
System.exit(0);
}
}
/**
* 为了能够方便的设置服务器的端口
* 显示在线的人数而设计了简单的用户界面
*/
private void buildGUI(){
this.f = new JFrame("QQ服务器");
JLabel portLab = new JLabel("端口号: ");
portF = new JTextField(20);
/*默认端口号*/
portF.setText("9999");
JLabel oneLinePersonLab = new JLabel("在线人数: ");
personsLab = new JLabel("0");
final JButton cfmB = new JButton("确定");
JPanel buttonP = new JPanel();
buttonP.setLayout(new FlowLayout(FlowLayout.CENTER));
buttonP.add(cfmB);
cfmB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
/*
*save useful info
*/
preServe(cfmB);
serve();
}
});
Container c = f.getContentPane();
GridBagLayout gb = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
c.setLayout(gb);
MyUtilities.addGCmp(c, portLab, gb, gbc, 0,0,1,1,1,1);
MyUtilities.addGCmp(c, portF, gb, gbc, 1,0,1,1,1,1);
MyUtilities.addGCmp(c, oneLinePersonLab, gb, gbc, 0,1,1,1,1,1);
MyUtilities.addGCmp(c, personsLab, gb, gbc, 1,1,1,1,1,1);
MyUtilities.addGCmp(c, buttonP, gb, gbc, 0,2,2,1,1,1);
this.f.setIconImage(new ImageIcon("Img/85.gif").getImage());
this.f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
isRunning = false;
notifyAllUserExit();
System.exit(0);
}
});
this.f.setSize(400,200);
this.f.setResizable(false);
this.f.setVisible(true);
}
private void notifyAllUserExit(){
this.user.clear();
}
private boolean loadDBDriver(String DBName,String user,String pw)
{
String url = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName="+DBName;
try {
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
this.con = DriverManager.getConnection(url,user,pw);
return true;
} catch (Exception e){
e.printStackTrace();
JOptionPane.showMessageDialog(null,
"加载数据库时候出错!","连接错误",JOptionPane.ERROR_MESSAGE);
}
return false;
}
private void preServe(JButton b){
b.setVisible(false);
port = Integer.parseInt(portF.getText());
portF.setEditable(false);
Font f = new Font("黑体",Font.BOLD,30);
this.personsLab.setFont(f);
isRunning = true;
}
private void serve(){
//接收用户连接
new Thread(new Runnable(){
public void run(){
connectClient();
}
}).start();
//用于接收用户退出的申请
}
//用于接收用户登录的线程
private void connectClient(){
try{
ServerSocket s = new ServerSocket(this.port);
while(this.isRunning){
Socket sock = s.accept();
this.currentSocket = sock;
check();
}
}catch(Exception e)
{}
}
private void check(){
try{
this.output = new ObjectOutputStream(
this.currentSocket.getOutputStream());
this.input = new ObjectInputStream(
this.currentSocket.getInputStream());
Message msg = ((Message)this.input.readObject());
String sysMsg = msg.sysMsg;
if(sysMsg.equals("登录")){
dealLogin(msg.msg);
}else if(sysMsg.equals("申请")){
String number = null;
try{
number = dealRequest(msg.msg);
}catch(SQLException e)
{
e.printStackTrace();
}
//注册成功
if(number != null){
this.output.writeObject(new Message("注册成功",number));
}else{
this.output.writeObject(new Message("注册失败",""));
}
this.currentSocket.close();
}
else if(sysMsg.equals("下线")){
this.currentSocket.close();
dealUserQuit(msg.msg);
}
}catch(Exception e)
{}
}
private void dealUserQuit(String qqNumber){
this.user.remove(qqNumber);
this.userInfo.remove(qqNumber);
this.personsLab.setText(String.valueOf(this.user.size()));
this.personsLab.repaint();
/*更新用户中的在线列表*/
Collection<String> coll = this.user.keySet();
java.util.Iterator<String> ite = coll.iterator();
while(ite.hasNext())
{
String key = ite.next();
MySocket s = this.user.get(key);
try {
s.output.writeObject(new Message("有人下线",qqNumber));
} catch (IOException e)
{}
}
}
/**
*检查登录是否合法,如果合法记录它的用户某些信息,便于传给List
*/
private boolean isValidClient(String num,String pas){
boolean isValid = false;
try {
PreparedStatement ps = con.prepareStatement(
"SELECT Password,Age,Name,Sex,Nickname,Email,IconName,MySign FROM Client_Tab WHERE Number=?");
ps.setString(1,num);
ResultSet rs = ps.executeQuery();
//如果没有判断rs.next()将出错
if(rs.next()){
isValid = (pas.equals(rs.getString("Password")));
//记录用户信息
if(isValid){
ClientInfo info = new ClientInfo();
info.number = num;
info.age = rs.getInt("Age");
info.iconName = rs.getString("IconName");
info.nickName = rs.getString("Nickname");
info.mySign = rs.getString("MySign");
info.sex = rs.getString("Sex");
info.name = rs.getString("Name");
info.email = rs.getString("Email");
info.ip = this.currentSocket.getInetAddress().getHostAddress();
this.currentUserInfo = info;
this.userInfo.put(info.number,this.currentUserInfo);
}
}
else
isValid = false;
}catch(Exception e)
{}
return isValid;
}
private void dealLogin(String info)throws Exception{
StringTokenizer st = new StringTokenizer(info);
String ip = (String)st.nextElement();
String num = (String)st.nextElement();
String pas = (String)st.nextElement();
if(isValidClient(num,pas)&& !this.user.containsKey(num)){
this.output.writeObject(new Message("valid",""));
/*保存连接*/
this.user.put(num, new MySocket(this.currentSocket,this.output));
/*更新在现的人数*/
this.personsLab.setText(String.valueOf(this.user.size()));
this.personsLab.repaint();
/* 向已经登录的OnlineFrm发送所有的在线列表信息*/
this.sendOnLineList(num);
}
//不合法的登录,断开连接,移除暂存的连接
else{
this.output.writeObject(new Message("Invalid",""));
this.currentSocket.close();
}
}
private void sendOnLineList(String currentNum)throws Exception{
/*向新登录的人发送所有的在线人员*/
Collection<ClientInfo> infoValueColl = this.userInfo.values();
java.util.Iterator<ClientInfo> iteInfo = infoValueColl.iterator();
while(iteInfo.hasNext()){
this.output.writeObject(iteInfo.next());
}
/*向已经在线的人发送新增的人员信息*/
Collection<String> coll = this.user.keySet();
java.util.Iterator<String> ite = coll.iterator();
while(ite.hasNext())
{
String key = ite.next();
if(!currentNum.equals(key)){
MySocket s = this.user.get(key);
s.output.writeObject(this.currentUserInfo);
}
}
}
private String createNumber(){
Statement st;
String number = null;
try {
st = con.createStatement();
ResultSet rs = st.executeQuery("SELECT Number FROM Client_Tab");
//如果没有判断rs.next()将出错
while(rs.next()){
if(rs.isLast()){
number = rs.getString("Number");
}
}
System.exit(0);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
number = String.valueOf(Integer.valueOf(number)+1);
System.out.println(number);
return number;
}
/**
* 处理用户申请号码的线程工作方法
*/
private String dealRequest(String info)throws SQLException {
String number; //create a number
number = createNumber();
StringTokenizer st = new StringTokenizer(info,"&");
String sex = st.nextToken();
String nickname = st.nextToken();
String email = st.nextToken();
String name = st.nextToken();
String age = st.nextToken();
String password = st.nextToken();
String iconName = st.nextToken();
String sign = st.nextToken();
String sqlAppend = "INSERT INTO Client_Tab" +
"(Number,Password,Name,Age,Sex,Nickname,Email,IconName,MySign)" +
"VALUES(?,?,?,?,?,?,?,?,?)";
PreparedStatement ps = con.prepareStatement(sqlAppend);
ps.setString(1,number);
ps.setString(2,password);
ps.setString(3,name);
ps.setInt(4,Integer.parseInt(age));
ps.setString(5,sex);
ps.setString(6,nickname);
ps.setString(7,email);
ps.setString(8,iconName);
ps.setString(9,sign);
ps.executeUpdate();
//关闭ps
ps.close();
return number;
}
public static void main(String[] args){
new Server();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -