1、数据库用的mysql,一共有3张表,一张用户表user、一张朋友列表friend和一张消息表message。

1 User table      用户表
uid 主键自动生成
userName 昵称
userPwd 密码
userSex 性别
userPho 用户头像,有默认头像
2 Friend table 好友列表
fid 主键自动生成
uid --> fk 用户id,外键
fuid --> 朋友的id
fName 好友名称
3 Messages table 消息表
mid 消息id,主键自动生成
fromid --> fk from id 发送者id
tofid --> fk to id 接收者id
msg 消息内容
mtime 发送时间

2、服务器端架构

3、model包解析

public class User{//1 用户类
private String userName;//用户名
private String userPwd;//用户密码
private String userSex;//用户性别
private String userPho;//用户照片
...
public class Friend {//2 朋友类
private int uid;//用户id
private int fuid;//friend id
private String fName;//用户的朋友名字
...
public class FriendList extends ArrayList<Friend>{//3 朋友列表类
/**
*
*/
private static final long serialVersionUID = 1L;
private FriendList friendlist;
public FriendList() {
friendlist = null;
}
}
public class Messages{//4 消息类
private int fromId;
private int toId;
private String msg;
private String mtime;
public Messages() { }

4、db包解析

主要作用是加载类,获取mysql数据库的连接

public class DBConnection {
public static final String DBURL = "jdbc:mysql://localhost:3306/qq";
public static final String DBUSER = "root";
public static final String DBPASS = "root";
public static final String DBDRIVER = "com.mysql.jdbc.Driver"; static {
try {
Class.forName(DBDRIVER);//加载类
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//返回Connection
public Connection getConnect() throws SQLException{
return DriverManager.getConnection(DBURL,DBUSER,DBPASS);
}
//关闭资源
public void close(Connection con, Statement sta, ResultSet rs) {
try {
rs.close();
if(con != null) {
con.close();
}
if(sta != null) {
sta.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

5、util包解析

第一个类Packager

public class Packager {
//用于登录数据包的分析
public String loginPackager(String operate,String friends,String result) {
StringBuffer mes = new StringBuffer("");
mes.append("operate:" + operate + "\n");
mes.append("content:" + friends);
mes.append("result:" + result + "\n");
return mes.toString();
}
//用于发送数据包的分析
public String sendPackager(String operate,String msg,String result) {
StringBuffer mes = new StringBuffer("");
mes.append("operate:" + operate + "\n");
mes.append("content:" + "\n");
mes.append("result:" + result + "\n");
return mes.toString();
}
}

第二个类Parser

public class Parser {
//解析类
//用于解析获取的请求类型是什么,比如登录、发送消息
public String getOperate(String request) {
String[] message = request.split("\n");
String operate = message[0].substring(8,message[0].length());
return operate;
}
//获取内容
public String getContent(String request) {
String[] message = request.split("\n");
String content = message[1].substring(8,message[1].length());
return content;
}
//获取发送的消息
public Messages parseMessages(String content) {
String[] mes = content.split("#");
int toId = Integer.parseInt(mes[0]);
String message = mes[1];
Messages msg = new Messages();
msg.setToId(toId);
msg.setMsg(message);
return msg;
}
//将字符串解析为用户类,返回用户类
public User parseUser(String content) {
//分隔符为#
String[] mes = content.split("#");
//第一个是用户名,第二个是密码
String userName = mes[0];
String userPwd = mes[1];
User user = new User();
user.setUserName(userName);
user.setUserPwd(userPwd);
return user;
}
}

  

6、controll包解析

controller类解析

//控制器
public class Controller {
//无参构造函数
public Controller() { }
//相应请求
public String doResponse(String request,String ip) {
Parser parser = new Parser();
String operate = parser.getOperate(request);//用于解析用户的请求操作是什么
String content = parser.getContent(request);//获取请求的内容
String response = null;//相应字符串
String friends = null;//朋友
if("login".equals(operate)) {//判断是否是登录请求
int uid = login(content);//返回该用户的id,如果没有该用户返回0
String result = null;
if(uid != 0) {
//将该用户的主键和ip地址加入管理客户端类中
ManageClients.addIps(new Integer(uid), ip);
result = "success";//如果登陆成功,那么获得该用户的所有朋友列表
friends = getFriends(uid);
}else{
result = "fail";//登录失败
}
Packager packager = new Packager();
response = packager.loginPackager(operate,friends,result);
}else if("sendMessage".equals(operate)) {//如果是发送消息
Messages msg = parser.parseMessages(content);
int toId = msg.getToId();//找到要接受者的id
String ipaddress = ManageClients.ips.get(new Integer(toId)).toString();//通过id 获得ip地址
ServerThread sendto = (ServerThread)ManageClients.clients.get(ipaddress);//通过ip地址获取接受者的线程
sendto.send(msg.getMsg());//向发送端发送信息
Packager packager = new Packager();
String result = "success";
response = packager.sendPackager(operate,null,result);
}
return response;
}
public String getFriends(int uid) {
String sql = "select fid,uid,fuid,fName from friend where uid=" + uid;
DBConnection dbc = new DBConnection();
Connection con = null;
Statement sta = null;
ResultSet rs = null;
StringBuilder sb = new StringBuilder("");
try {
con = dbc.getConnect();
con = dbc.getConnect();
sta = con.createStatement();
rs = sta.executeQuery(sql);
while(rs.next()) {
sb.append(rs.getInt(1)+"#" + rs.getInt(2) + "#" + rs.getInt(3) + "#" + rs.getString(4) + "\n");
}
} catch (SQLException e) {
e.printStackTrace();
}
return sb.toString();
}
public int login(String content) {//登录操作,登陆成功,返回朋友列表,否则返回错误原因
Parser parser = new Parser();
User user = parser.parseUser(content);//获取用户类
//然后去数据库中查询是否有该用户,如果有该用户,那么返回该用户的主键id
String sql = "select uid,userPwd from user where userName='" + user.getUserName() +"'";
DBConnection dbc = new DBConnection();
Connection con = null;
Statement sta = null;
ResultSet rs = null;
String dbpwd = null;
int uid = 0;
try {
con = dbc.getConnect();
sta = con.createStatement();
rs = sta.executeQuery(sql);
while(rs.next()) {
uid = rs.getInt(1);
dbpwd = rs.getString(2);
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
dbc.close(con, sta, rs);
}
if(dbpwd != null && dbpwd.equals(user.getUserPwd()) && uid != 0) {
return uid;
}else{
uid = 0;
return uid;
}
}

7、server包解析

7.1 Server类 开启监听端口,不断监听请求的用户

public class Server {
public static void main(String[] args) {
new Server();
}
public Server()
{
ServerSocket serversocket = null;
Socket socket = null;
try {
serversocket = new ServerSocket(5000);
System.out.println("服务器已经启动,正在监听5000端口");
while(true) {
socket = serversocket.accept();
String ip = socket.getLocalAddress().getHostAddress();
ServerThread st = new ServerThread(socket,ip);//服务器端线程
st.start();
ManageClients.addClients(ip, st);//将该线程添加到ManageClients类中
int port = socket.getPort();
System.out.println("连接上的客户端ip:" + ip + ",端口号:" + port);
}
} catch (IOException e) {
e.printStackTrace();
} }
}

7.2 ServerThread类 ,用于转发消息

public class ServerThread extends Thread{
private Socket socket;
private String ip;
private InputStream in;
private OutputStream out;
private static final int SIZE = 1024;
public Socket getSocket(){
return socket;
}
public ServerThread(Socket socket,String ip) {
this.socket = socket;
this.ip = ip;
try {
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public void send(String mes) {
try {
out.write(mes.getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
try {
if(in != null){
in.close();
in = null;
}
if(out != null) {
out.close();
out = null;
}
if(socket != null) {
socket.close();
socket = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
try {
byte[] buffer = new byte[SIZE];
int index = in.read(buffer);
String message = new String(buffer,0,index);//获取客户端发送过来的请求
Parser parser = new Parser();
String operate = parser.getOperate(message);
Controller controller = new Controller();
if(operate.equals("exit")) {
break;
} String response = controller.doResponse(message,ip);//服务器处理发送过来的消息,如果不是收获
//的操作不是exit
if(response != null)
send(response);//向客户端发送请求操作的结果
} catch (IOException e) {
e.printStackTrace();
}finally{
close();
}
} }

7.3 ManageClients

public class ManageClients {
//管理客户端 ,用HashMap存储用户ip和线程的键值对
public static HashMap<String,ServerThread> clients = new HashMap<String,ServerThread>();//string sender
//用于用户主键 和ip之间的键值对
public static HashMap<Integer,String> ips = new HashMap<Integer,String>();
public static void addClients(String senderip, ServerThread st) {
clients.put(senderip, st);
}
public static void addIps(Integer i, String ip) {
ips.put(i, ip);
}
}

服务器端结束 ,启动Server中的main 函数,监听是否有客户端请求

基于Android的简单聊天工具-服务器端的更多相关文章

  1. 基于WebServices简易网络聊天工具的设计与实现

    基于WebServices简易网络聊天工具的设计与实现 Copyright 朱向洋 Sunsea ALL Right Reserved 一.项目内容 本次课程实现一个类似QQ的网络聊天软件的功能:服务 ...

  2. [更新Github地址]python学习,自己写了个简单聊天工具mychat

    最近在学习python,自己写了个最最简单的聊天工具mychatv0.1. 第一版,完成基本的聊天功能. GUI用的是自带的TKinter,用到的模块主要就是socket(网络编程), thread( ...

  3. C#基于Socket的简单聊天室实践

    序:实现一个基于Socket的简易的聊天室,实现的思路如下: 程序的结构:多个客户端+一个服务端,客户端都是向服务端发送消息,然后服务端转发给所有的客户端,这样形成一个简单的聊天室功能. 实现的细节: ...

  4. Android 即时语音聊天工具 开发

    使用融云SDK 1. 功能需求分析 1.1 核心功能需求: * 即时通讯 * 文字聊天 * 语音聊天 1.2 辅助功能需求: * 注册.登录 * 好友添加功能 * 好友关系管理 2. 融云即时通讯平台 ...

  5. c# UDP/TCP协议简单实现(简单聊天工具)

    长时间没有摸这两个协议,写个代码温习下 下面是界面 [服务器界面] [登陆界面] [好友列表界面(我登陆了2个)] [聊天界面] 下面大致讲解下用到的内容 1.用户登陆于服务器通信用到的tcp协议,服 ...

  6. Netty 系列八(基于 WebSocket 的简单聊天室).

    一.前言 之前写过一篇 Spring 集成 WebSocket 协议的文章 —— Spring消息之WebSocket ,所以对于 WebSocket 协议的介绍就不多说了,可以参考这篇文章.这里只做 ...

  7. 基于GUI的简单聊天室01

    运用了Socket编程,gui,流的读入和写出,线程控制等 思路: 1.首先是在客户端中先建立好聊天的GUI 2.建立服务器端,设置好端口号(用SocketServer),其中需要两个boolean变 ...

  8. java自己写的简单聊天工具SimpleQQ感悟

    Demo如下: 客户端: /* * 一个简单的QQ * 2013-8-1 * @李志杰 */ package SimpleQQ_Client; import java.awt.*; import ja ...

  9. 基于Android的串口聊天室 (基于tiny4412) 一

    一.平台介绍 硬件平台: tiny4412ADK + S700 4GB Flash Android版本:Android-5.0.2 Linux版本: Linux-3.0.86 Bootloader:S ...

随机推荐

  1. 重载和const参数

    const仅能用于在定义函数签名时,区分是为引用定义参数,还是为指针定义参数.定义基本类型type(如int等),从重载的观点来看,const int和int是相同的. const long& ...

  2. HTML5+ API 学习

    HTML5+ API 模块整理 API Reference 模块 中文 模块介绍 Accelerometer 加速计 管理设备加速度传感器,用于获取设备加速度信息,包括x(屏幕水平方向).y(垂直屏幕 ...

  3. JAVA的泛型与反射的联合应用

    通过泛型与反射的结合,可以编写框架来使开发更容易,这里演示的是BaseDao部分的简单使用. BaseDao部分代码: public abstract class BaseDao<T>{ ...

  4. request设置属性 一般当做下一个页面的结果集

    request设置属性 一般当做下一个页面的结果集

  5. Codeforces633H-Fibonacci-ish II

    题目 斐波那契数列\(f\),\(f\_1=f\_2=1,\ f\_n=f\_{n-1}+f\_{n-2}\ (n>2)\). 给定长度为\(n\ (n\le 30000)\)的数列\(a\), ...

  6. 前端基础:HTML标签(上)

    前端基础:THML HTML初始 1.web服务本质 import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) so ...

  7. Django 2.0 学习(08):Django 自动化测试

    编写我们的第一个测试 确定bug 幸运的是,在polls应用中存在一个小小的bug急需修复:无论Question的发布日期是最近(最后)的日期,还是将来很多天的日期,Question.was_publ ...

  8. BZOJ1997:[HNOI2010]PLANAR——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=1997 https://www.luogu.org/problemnew/show/P3209 若能 ...

  9. CodeForces - 50A Domino piling (贪心+递归)

    CodeForces - 50A Domino piling (贪心+递归) 题意分析 奇数*偶数=偶数,如果两个都为奇数,最小的奇数-1递归求解,知道两个数都为1,返回0. 代码 #include ...

  10. 【BZOJ 3811】玛里苟斯 大力观察+期望概率dp+线性基

    大力观察:I.从输出精准位数的约束来观察,一定会有猫腻,然后仔细想一想,就会发现输出的时候小数点后面不是.5就是没有 II.从最后答案小于2^63可以看出当k大于等于3的时候就可以直接搜索了 期望概率 ...