手机客户端连接服务器进行登录验证
最近两个月感觉还是学了不少东西,安卓了解更加透彻,web开发也能拿的出手,php也开始上手了。总会有不想写代码的时候,这时就来总结总结学习的东西也挺好的。
现在主要存在两种网络模式,B/S和C/S。相对于B/S,C/S可能要稍微复杂一点,需要我们开发客户端。C/S可以使用tcp/ip协议和http协议进行通信。我们从简单的开始,看一下手机客户端怎么用这两种方式连接后台验证密码成功登陆。
一、使用http协议
我们需要一个web服务器,至于这个服务器怎么搭建,用servlet+jdbc还是使用hibernate,spring这些框架都是可以实现的。这里我使用的是hibernate,新建一个web工程,hibernate配置文件代码如下:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.username">XXX</property> <property name="hibernate.connection.password">XXX</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@ip:port:dataname</property> <property name="show_sql">true</property> <mapping resource="com/xyj/domain/User.hbm.xml"/> </session-factory> </hibernate-configuration>
package com.xyj.hibernate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.hibernate.Query; import org.hibernate.Session; import org.junit.Test; import com.zifeiyu.domain.Score; import com.zifeiyu.domain.Student; /* * 提供数据库的查询服务,包括密码 */ public class DBService { public static String getPassword(String username) { Session session = null; try { session = hibOracleUtils.getSession(); String hql="from User as s where s.username=?"; Query query=session.createQuery(hql); //填充占位符 query.setString(0, username); User user=(User) query.uniqueResult(); return user.getpassword(); }finally { if (session != null) { session.close(); } } } }
服务器类:
public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter pw = resp.getWriter(); String username= req.getParameter("username"); String password = req.getParameter("password"); System.out.println("=========username========" + username); System.out.println("=========password========" + password); String PASSWD; try { //根据用户名从数据库取出密码(数据库中存放的是md5加密后的密码,客户端传过来的也是加密后的,保证了安全性) PASSWD = DBService.getPassword(username); if (password.equals(PASSWD)) { pw.print(true); } else { pw.print(false); } } catch (Exception e) { pw.print(false); } } }
这样后台服务器就搭建好了(上面仅仅贴出了重要代码),再来看看手机客户端怎么发送http请求。
package com.xyj.login; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; public class HttpClientToServer { String urlAddress = "http://localhost:8081/AndroidServer/login.do"; public HttpClientToServer(){ } public String doPost(String USER_XH,String password){ HttpPost httpPost = new HttpPost(urlAddress); List params = new ArrayList(); NameValuePair pair1 = new BasicNameValuePair("username", username); NameValuePair pair2 = new BasicNameValuePair("password", password); params.add(pair1); params.add(pair2); HttpEntity he; try { he = new UrlEncodedFormEntity(params, "gbk"); httpPost.setEntity(he); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } HttpClient hc = new DefaultHttpClient(); try { HttpResponse ht = hc.execute(httpPost); if(ht.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ HttpEntity het = ht.getEntity(); InputStream is = het.getContent(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String response = ""; String readLine = null; while((readLine =br.readLine()) != null){ //response = br.readLine(); response = response + readLine; } is.close(); br.close(); //String str = EntityUtils.toString(he); System.out.println("========="+response); return response; }else{ return "error"; } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); return "exception"; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return "exception"; } } }
然后根据返回值是TRUE或者FALSE自定义提示消息就行了。
二、使用tcp/ip协议
服务器端使用jdbc连接数据库,代码如下:
package myServer; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class myServerSocket { public static void main(String[] args) { ServerSocket serverSocket = null; Socket socket = null; // 监听8888端口 try { serverSocket = new ServerSocket(8888); System.out.println("服务器开启"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } while (true) { try { // 有请求接入 socket = serverSocket.accept(); //开启线程处理请求 new serverThread(socket).start(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
package myServer; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.mysql.jdbc.ResultSetMetaData; public class serverThread extends Thread { public Socket socket = null; DataInputStream dataInputStream = null; DataOutputStream dataOutputStream = null; String[] arr; // 用于连接数据库 static String DBDrive = "com.mysql.jdbc.Driver"; static String connStr = "jdbc:mysql://localhost:3306/mydb"; // 连接对象 static Connection conn = null; // 语句对象 PreparedStatement statement = null; // 查询结果对象 ResultSet resultSet = null; public serverThread(Socket socket) { this.socket = socket; // 连接mysql数据库 linkMySql(); } private void linkMySql() { // 加载数据库驱动程序 try { Class.forName(DBDrive); System.out.println("驱动成功"); } catch (ClassNotFoundException e) { e.printStackTrace(); } try { conn = DriverManager.getConnection(connStr, "XXX", "XXX"); System.out.println("连接成功"); } catch (SQLException e) { e.printStackTrace(); } } @Override public void run() { super.run(); try { dataInputStream = new DataInputStream(socket.getInputStream()); // 读取消息 String msg = dataInputStream.readUTF(); arr = msg.split(" "); System.out.println(msg); // 响应请求 dataOutputStream = new DataOutputStream( socket.getOutputStream()); try { checkInfo(); } catch (SQLException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } // 关闭相关的流 try { if (dataInputStream != null) dataInputStream.close(); if (dataOutputStream != null) dataOutputStream.close(); if (socket != null) socket.close(); if(conn!=null) conn.close(); } catch (IOException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } private void checkInfo() throws SQLException { String sql="select * from user where username=?"; List<Object> params=new ArrayList<Object>(); params.add(arr[0]); //得到该用户的所有信息 Map<String, Object> map=findSimpleResult(sql,params); //输出 System.out.println(map); //通过键值得到密码 String psd=(String) map.get("psd"); if(psd==null){ try { dataOutputStream.writeUTF("该用户不存在"); } catch (IOException e) { e.printStackTrace(); } }else{ try { if(psd!=null&&psd.equals(arr[1])) dataOutputStream.writeUTF("登录成功"); else dataOutputStream.writeUTF("密码有误"); } catch (IOException e) { e.printStackTrace(); } } } //通过用户名得到该用户的所有信息 private Map<String, Object> findSimpleResult(String sql, List<Object> params) throws SQLException { Map<String, Object> map=new HashMap<String,Object>(); int index=1; statement = conn.prepareStatement(sql); if(params!=null&&!params.isEmpty()){ for(int i=0;i<params.size();i++){ statement.setObject(index++, params.get(i)); } } resultSet=statement.executeQuery(); java.sql.ResultSetMetaData metaData=resultSet.getMetaData(); int col_len=metaData.getColumnCount(); while(resultSet.next()){ for(int i=0;i<col_len;i++){ String col_name=metaData.getColumnName(i+1); Object col_value=resultSet.getObject(col_name); if(col_value==null){ col_value=""; } map.put(col_name, col_value); } } return map; } }
客户端代码:
package com.xyj.client; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import com.xyj.help.config; import android.os.Handler; import android.os.Message; public class loginclientThread extends Thread { private String name; private String psd; Handler handler; String response; Socket socket; DataInputStream dataInputStream; DataOutputStream dataOutputStream; public loginclientThread(String name, String psd, Handler handler) { this.name = name; this.psd = psd; this.handler = handler; } public void run() { // 创建套接字 try { socket = new Socket("122.207.54.5", 8888); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { dataInputStream = new DataInputStream(socket.getInputStream()); dataOutputStream = new DataOutputStream(socket.getOutputStream()); // 发送请求 dataOutputStream.writeUTF(toString()); // 得到返回消息 response = dataInputStream.readUTF(); Message message = Message.obtain(); message.what = config.islogin; message.obj = response; handler.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } try { dataInputStream.close(); dataOutputStream.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public String toString() { //需要传送的参数多建议采用json传递 return name + " " + psd + " "; } }
以上就是这两种协议通信的主要代码。每天进步一点点,我们都可以非常棒