• 基于Android的简单聊天工具-服务器端


    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 + "
    ");
    		mes.append("content:" + friends);
    		mes.append("result:" + result + "
    ");
    		return mes.toString();
    	}
    	//用于发送数据包的分析
    	public String sendPackager(String operate,String msg,String result) {
    		StringBuffer mes = new StringBuffer("");
    		mes.append("operate:" + operate + "
    ");
    		mes.append("content:" + "
    ");
    		mes.append("result:" + result + "
    ");
    		return mes.toString();
    	}
    }
    

    第二个类Parser

    public class Parser {
    	//解析类
    		//用于解析获取的请求类型是什么,比如登录、发送消息
    	public String getOperate(String request) {
    		String[] message = request.split("
    ");
    		String operate = message[0].substring(8,message[0].length());
    		return operate;
    	}
    	//获取内容
    	public String getContent(String request) {
    		String[] message = request.split("
    ");
    		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) + "
    ");
    			}
    		} 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 函数,监听是否有客户端请求

  • 相关阅读:
    线程间的通信 与 线程池
    线程同步
    静态代理模式
    多线程状态
    线程、进程、多线程
    Java面向对象之泛型
    ConstraintLayout 用法
    搞NDK开发
    Linux基础命令【记录】
    c# 的一些基本操作或属性
  • 原文地址:https://www.cnblogs.com/fankongkong/p/6389211.html
Copyright © 2020-2023  润新知