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. ADO.NET基础必备之SqlCommand.Execute三方法

    SqlCommand.ExecuteNonQuery 方法   对连接执行 Transact-SQL 语句并返回受影响的行数. ――语法: public override int ExecuteNon ...

  2. JSON字符串书写

      { "XXX公司": [ { "name": "IT部", "mebers": [ { "维护人员&quo ...

  3. 【python】windows7下怎样安装whl

    windows7 python2.7 1.用管理员方式打开cmd 2.首先通过pip命令安装wheel 如果提示’pip’不是内部或外部命令,也不是可运行的程序或批处理文件 ①将python安装目录下 ...

  4. 【bzoj4401】块的计数 结论题

    题目描述 给出一棵n个点的树,求有多少个si使得整棵树可以分为n/si个连通块. 输入 第一行一个正整数N,表示这棵树的结点总数,接下来N-1行,每行两个数字X,Y表示编号为X的结点与编号为Y的结点相 ...

  5. OpenStack Queens版本Horizon定制化开发

    工具环境 1.VMware workstation 12+: 2.Ubuntu系统+Linux Pycharm: 3.OpenStack Queens版本Horizon代码: 问题及解决 1.项目代码 ...

  6. openstack之keystone部署

    前言 openstack更新频率是挺快的,每六个月更新一次(命名是是以A-Z的方式,Austin,Bexar...Newton).博主建议大家先可一种版本研究,等某一版本研究透彻了,在去研究新的版本. ...

  7. POJ3422:Kaka's Matrix Travels——题解

    http://poj.org/problem?id=3422 题目大意: 从左上角走到右下角,中途取数(数>=0),然后该点的数变为0,求走k的总价值和最大值. ———————————————— ...

  8. BZOJ1026:[SCOI2009]windy数——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1026 Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2 ...

  9. Visual Studio 2010如何利用宏

    最近在做后台代码的拆分,由于机器升级,原来装的添加注释的插件不能用了. 看来只有自己想办法了,看了下利用宏添加注释与把项目展开.折叠的方式: 参考了以下几个内容: 1.Visual Studio 20 ...

  10. AtCoder Regular Contest 081 E - Don't Be a Subsequence(字符串DP)

    引用自:onion_cyc 字符串DP一直不是强项...以后没思路的题就想DP和网络流23333333 f[i]表示从i开始的后缀非子序列的最短长度  pos[i][j]表示从i开始的j字符最早出现位 ...