• 特别数据传输方面,初学者很可能犯一个很容易犯的错误,就是客户端通过字节数组或者对象服务器端交换数据,但最后会发现它们都很不可行(用字节流时在服务器端交互数据的时候很难操作控制,很难让服务器端知道...
    对于初学者,Android的网络通信是大家都喜欢但是又会感觉很难处理的模块。特别数据传输方面,初学者很可能犯一个很容易犯的错误,就是客户端通过字节数组或者对象与服务器端交换数据,但最后会发现它们都很不可行(用字节流时在与服务器端交互数据的时候很难操作控制,很难让服务器端知道什么时候应该开始下一步的处理;用对象交换数据的时候,交换要求是客户端和服务器端必须有类名、包名、内容完全相同的类,这样很难做到跨语言的通讯)。因此我采用了字符流的形式传送数据并对网络的访问做了一系列的封装,希望能够帮助到你。废话就不多说了,开始切入正题吧。
    
    客户端与服务器端交互主要的思想为:客户端把数据转化为JSON格式的字符串再发给服务器端(字符串主要包含两个部分:操作码,数据。转化方式为:把数据传入到模板类的对象中,通过FastJson把对象转化为字符串)。服务器端接收到字符串之后再把字符串转化为模板类的对象(转化方式为:先通过FastJson把字符串转化为JSON对象格式的数据,再把JSON对象转化为模板类的对象),服务器端根据操作码来做不同的处理,处理之后把数据封装到模板类的对象中,FastJson再把模板类的对象转化为字符串传给客户端,客户端接收到字符串数据之后再把字符串数据转化为模板类的对象(转化方式同上),客户端再通过模板类做相应的处理。
    
    客户端发送给服务器端的数据主要格式为:
    
    ```
    {
    	code:1,
    	data:[
    	{},{}
    	]
    }
    ```
    服务器端发送给客户端的数据主要格式为:
    
    ```
    {
    	ok:true,
    	data:{}
    }
    ```
    或者
    
    ```
    {
    	ok:true,
    	data:[
    	{},{}
    	]
    }
    ```
    
    看起来是不是很简单呢,那么开始代码讲解了吧。
    
    **安卓端:**
    主要使用到了如下几个类:
    数据请求模板类RequestMessage(主要用来封装发给服务器端的数据) :
    
    ```
    package com.szhushou.ssp.connection;
    
    import java.util.Map;
    
    public class RequestMessage {
    
        private Integer code;//操作码
        private Map data;//传送给服务器端的数据
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public void setData(Map data) {
            this.data = data;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public Map getData() {
            return data;
        }
    }
    
    ```
    网络传输核心类SocketConnection(主要用来封装最基本的数据传输类):
    
    ```
    package com.szhushou.ssp.connection;
    
    import android.util.Log;
    
    import com.alibaba.fastjson.JSON;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.Socket;
    
    public class SocketConnection {
        private final static String TAG = "SocketConnection";
        private final static String END = "#end#";//用来结束发送的字符串
        private Socket client = null;
        private BufferedReader ois = null;
        private PrintStream oos = null;
    
        public SocketConnection(String ip, int host) throws IOException {
            client = new Socket(ip, host);
            oos = new PrintStream(client.getOutputStream());
            ois = new BufferedReader(new InputStreamReader(client.getInputStream()));
        }
    
        public String requestData(RequestMessage messageOut) throws IOException {
            String result;
            String json = JSON.toJSONString(messageOut);
            sendString(oos, json);
            result = readString(ois);
            Log.i(TAG, result);
            oos.close();
            ois.close();
            if (!client.isClosed()) {
                client.close();
            }
            return result;
        }
    	/**
    	*用来读取输入流的内容
    	*/
        private String readString(BufferedReader ois) throws IOException {
            String result;
            String bufferText;
            StringBuffer resultBuffer = new StringBuffer();
            while (!(bufferText = ois.readLine()).equals(END)) {
                resultBuffer.append(bufferText);
            }
            result = resultBuffer.toString();
            return result;
        }
    
    	/**
    	*用来写入数据到输出流
    	*/
        private void sendString(PrintStream out, String text) {
            out.println(text);
            out.println(END);
            out.flush();
        }
    }
    ```
    业务逻辑的数据传输类Connection(主要用来对SocketConnection 进行进一步的封装处理,用来实现Android的网络线程异步处理,可以通过继承Connection类实现getData方法来做其他数据,如String格式的数据处理) :
    
    ```
    package com.szhushou.ssp.connection;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    
    import com.alibaba.fastjson.JSONObject;
    
    import java.io.IOException;
    
    
    /**
     * Created by xiaofeng on 2016-04-19.
     */
    public abstract class Connection {
        private final static String TAG="Connection";
        private String ip;
        private int host;
        public Connection(String ip,int host){
            this.ip=ip;
            this.host=host;
        }
    
        /**
         * 发送数据给服务器端
         * @param requestData 请求的数据
         * @param resultClass 接收的数据类的类型
         * @param successListener 访问数据成功的回调函数
         * @param failListener 访问数据失败的回调函数,失败主要包含两种失败,网络通信失败和服务器返回的ok值为false的失败,如果是网络通信失败onFile会返回IOException,如果是ok为false onFile会返回DataNullException
         * @param  模板类
         */
        public  void sendRequest(final RequestMessage requestData,Class resultClass,SuccessListener successListener,FailListener failListener){
            final MyHandler handler=new MyHandler(successListener,failListener,resultClass);
            new Thread(){
                @Override
                public void run(){
                    boolean ok;
                    String result;
                    try {
                        result = new SocketConnection(ip,host).requestData(requestData);
                        ok=true;
                    } catch (IOException e) {
                        e.printStackTrace();
                        result="";
                        ok=false;
                    }
                    Bundle bundle=new Bundle();
                    bundle.putBoolean("ok", ok);
                    bundle.putString("data", result);
                    Message message=new Message();
                    message.setData(bundle);
                    handler.sendMessage(message);
                }
            }.start();
        }
        /**
        *用来处理异步通讯
        */
        private class MyHandler extends Handler {
            private SuccessListener mSuccessListener;
            private FailListener mFailListener;
            private Class mClass;
    
            public MyHandler(SuccessListener successListener,FailListener failListener, Class clazz) {
                super();
                this.mSuccessListener = successListener;
                this.mFailListener=failListener;
                this.mClass = clazz;
            }
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Bundle data = msg.getData();
                String result = data.getString("data");
                boolean ok = data.getBoolean("ok");
                Log.i(TAG,result);
                if(ok==true) {
                    JSONObject jsonObject=JSONObject.parseObject(result);
                    boolean isOk=jsonObject.getBoolean("ok");
                    if(isOk==true) {
                        T resultData = getData(jsonObject,mClass);
                        mSuccessListener.onResponse(resultData);
                    }else {
                        String remindText=jsonObject.getString("data");
                        if(remindText==null) {
                            mFailListener.onFile(new DataNullException());
                        }else {
                            mFailListener.onFile(new DataNullException(remindText));
                        }
                    }
                }else {
                    mFailListener.onFile(new IOException());
                }
            }
        }
    
        /**
         * ok值为false抛出的提示异常,如果服务器端未传递值给data,则调用getMessage返回的值是null,如果服务器端有传递值给data,则调用getMessage返回的值为data对应的值
         */
        public class DataNullException extends Exception{
            private String message;
            public DataNullException(){
                super();
            }
            public DataNullException(String detailMessage){
                super(detailMessage);
                message=detailMessage;
            }
    
            @Override
            public String getMessage() {
                return message;
            }
        }
        /**
         * 该方法用来给继承实现,主要是为了去处理结果数据为数组或者为单一对象问题
         * @param jsonObject 封装有数据的Json
         * @param mClass 返回结果的类型
         * @param  结果的类型
         * @return 转化后的结果
         */
        protected abstract  T getData(JSONObject jsonObject,Class mClass);
        public interface SuccessListener{
            public void onResponse(T t);
        }
        public interface FailListener{
            public void onFile(Exception e);
        }
    }
    
    ```
    Conection的扩展类,主要用来处理数据返回为单一对象的操作类ObjectConnection
    
    ```
    package com.szhushou.ssp.connection;
    
    import com.alibaba.fastjson.JSONObject;
    
    
    /**
     * Created by xiaofeng on 2016-04-19.
     */
    public class ObjectConnection extends Connection {
        public ObjectConnection(String ip, int host) {
            super(ip, host);
        }
    
        @Override
        protected  T getData(JSONObject jsonObject,Class mClass){
            return JSONObject.toJavaObject(jsonObject.getJSONObject("data"), mClass);
        }
    }
    
    ```
    Conection的扩展类,主要用来处理数据返回为对象数组的操作类ArrayConnection:
    
    ```
    package com.szhushou.ssp.connection;
    
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    
    
    /**
     * Created by xiaofeng on 2016-04-19.
     */
    public class ArrayConnection extends Connection {
        public ArrayConnection(String ip, int host) {
            super(ip, host);
        }
    
        @Override
        protected   T getData(JSONObject jsonObject, Class mClass) {
            return JSONArray.toJavaObject(jsonObject.getJSONArray("data"), mClass);
        }
    }
    
    ```
    核心类已经写完了,如果不能理解也不要紧,只需要会调用就可以了,以下是用于安卓端调用的核心方法。
    
    ```
    try {
                        Map map = new HashMap();
                        map.put("name", "client");
                        map.put("metter","hello world!");
                        RequestMessage requestMessage = new RequestMessage();
                        requestMessage.setCode(1);
                        requestMessage.setData(map);
                        new ObjectConnection("192.168.191.1",6000).sendRequest(requestMessage, ResponseContent.class, new Connection.SuccessListener() {
                            @Override
                            public void onResponse(ResponseContent responseContent) {
                            //TODO 用来处理接收到的数据,数据都封装到resposeContent中了
                            }
                        }, new Connection.FailListener() {
                            @Override
                            public void onFile(Exception e) {
                                Toasts.showShort("出现异常,识别失败");//TODO Toasts是为了简写Toast而写的工具类,你可以直接用Toast的语法修改回来就可以了。
                            }
                        });
                    } catch (IOException e) {
                        Toasts.showShort(MainViewActivity.this,"查询失败,文件读写异常");
                    }catch (Exception e) {
                        Toasts.showShort(MainViewActivity.this,"查询失败,其他异常");
                    }
    ```
    服务器发送给客户端的数据的数据封装类ResponseContent(具体业务的一部分,可以根据实际需求修改):
    
    ```
    package com.szhushou.ssp.model;
    
    public class ResponseContent{
    	private String name;
    	private String metter;
    	public void setName(String name) {
    		this.name = name;
    	}
    	public void setMetter(String metter) {
    		this.metter = metter;
    	}
    	public String getName() {
    		return name;
    	}
    	public String getMetter() {
    		return metter;
    	}
    	
    }
    ```
    客户端的代码就介绍完了,接下来就是服务器端的了
    
    **服务器端:**
    服务器端程序入口类ServerMain(主要用来接收客户端的连接信息,把信息传递给线程处理):
    
    ```
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import com.szhushou.ssps.util.SystemMethod;
    
    public class ServerMain
    {
    	private static final String TAG = "ServerMain";
    	public static void main(String args[]) 
    	{
    		ServerSocket server;
    		try {
    			server = new ServerSocket(FinalValue.host);
    			Socket client;
    			while(true)
    			{
    				client=server.accept();
    				new SportThread(client).start();
    			}
    		} catch (IOException e) {
    			System.out.println(TAG+" main "+e.getMessage());
    		}
    	}
    }
    ```
    服务器端事件处理线程SportThread(主要用来处理或者分发处理业务逻辑,这是修改的重点):
    
    ```
    package com.szhushou.ssps;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.Socket;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.szhushou.ssps.factory.FindImage;
    import com.szhushou.ssps.factory.Login;
    import com.szhushou.ssps.factory.MyFactory;
    import com.szhushou.ssps.model.client.RequestMessage;
    import com.szhushou.ssps.model.server.ResultMessage;
    import com.szhushou.ssps.util.BeanList;
    import com.szhushou.ssps.util.SpringFactory;
    import com.szhushou.ssps.util.SystemMethod;
    
    public class SportThread extends Thread {
    	private static final String TAG = "PublicMethod";
    	private final static String END = "#end#";// 用来结束发送的字符串
    
    	Socket client;
    
    	public SportThread(Socket client) {
    		this.client = client;//
    	}
    
    	public void run() {
    		try {
    			BufferedReader ois = new BufferedReader(new InputStreamReader(
    					client.getInputStream()));
    			PrintStream oos = new PrintStream(client.getOutputStream());
    			String requestData = readString(ois);
    			RequestMessage messageIn = JSON.parseObject(requestData,
    					RequestMessage.class);
    			ResultMessage messageOut = EventDispose(messageIn);
    			String resultData = JSONObject.toJSONString(messageOut);
    			sendString(oos, resultData);
    			ois.close();
    			oos.close();
    			if (!client.isClosed()) {
    				client.close();
    			}
    		} catch (IOException e) {
    			System.out.println(TAG+" run "+e.getMessage());
    		}
    	}
    
    	private String readString(BufferedReader ois) throws IOException {
    		String result;
    		String bufferText;
    		StringBuffer resultBuffer = new StringBuffer();
    		while (!(bufferText = ois.readLine()).equals(END)) {
    			resultBuffer.append(bufferText);
    		}
    		result = resultBuffer.toString();
    		return result;
    	}
    
    	private void sendString(PrintStream out, String text) {
    		out.println(text);
    		out.println(END);
    		out.flush();
    	}
    
    	public ResultMessage EventDispose(RequestMessage messageIn)
    			throws IOException {
    		ResultMessage messageOut = new ResultMessage();
    		int type = messageIn.getCode();
    		MyFactory factory = null;
    		try {
    			switch (type) {
    			case 1:
    				Map map=messageIn.getData();
    				String name=map.get("name");
    				String metter=map.get("metter");
    				//TODO处理消息...
    				
    				
    				ResponseMetter responseMetter=new ResponseMetter();
    				responseMetter.setMetter("already get message");
    				responseMetter.setName("server");
    				messageOut=new ResultMessage(false,responseMetter);
    				break;
    
    			default:
    				break;
    			}
    		} catch (Exception e) {
    			System.out.println(TAG+" EventDispose "+ e.getMessage());
    			messageOut=new ResultMessage(false,null);
    		}
    		return messageOut;
    	}
    }
    
    ```
    服务器端的接收消息模板类RequestMessage(主要是用来封装接收的信息的,慎改):
    
    ```
    package com.szhushou.ssps.model.client;
    
    import java.util.Map;
    
    public class RequestMessage
    {
    
        private Integer code;
        private Map data;
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public void setData(Map data) {
            this.data = data;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public Map getData() {
            return data;
        }
    }
    ```
    
    服务器端的返回结果模板类ResultMessage(主要用来封装发送给客户端的信息的,慎改):
    
    ```
    package com.szhushou.ssps.model.server;
    
    public class ResultMessage {
    	private boolean ok;
    	private Object data;
    	public ResultMessage(){
    		
    	}
    	public ResultMessage(boolean ok,Object data){
    		this.ok=ok;
    		this.data=data;
    	}
    	public void setOk(boolean ok) {
    		this.ok = ok;
    	}
    	public void setData(Object data) {
    		this.data = data;
    	}
    	public boolean isOk() {
    		return ok;
    	}
    	public Object getData() {
    		return data;
    	}
    }
    
    ```
    服务器端的消息封装类ResponseMetter(该类是用来封装具体信息的,内容和客户端的ResponseContent对应,可以根据业务修改和新建):
    
    ```
    package com.szhushou.ssps.model.server;
    
    public class ResponseMetter{
    	private String name;
    	private String metter;
    	public void setName(String name) {
    		this.name = name;
    	}
    	public void setMetter(String metter) {
    		this.metter = metter;
    	}
    	public String getName() {
    		return name;
    	}
    	public String getMetter() {
    		return metter;
    	}
    	
    }
    
    ```
    
    **提示:**
    本次代码的JSON部分主要使用带了阿里的开源代码FastJson,下载地址为:https://github.com/alibaba/fastjson/releases
    
    **总结:**
    经历了一上午,终于把博客写完了,如果有什么地方没考虑到部分,还望多多指教。后续有时间再继续跟进。
    展开全文
  • Socket解释: 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socketSocket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",...
  • 由于学院需要提交一个学年论文,正好借...目前智能终端中大部分采用了Google Android操作系统,因此,我在暑期重点研究了Android远程数据库通信的实现,并实现了一套可行的实现方案。 一、问题的引入 Android在数据存储
  • 实现Android客户端服务器的交互,客户端采用Android Studio开发,Web服务器采用MyEclipse开发,数据库使用MySQL,采用Hibernate框架开发
  • Android中的数据库连接池 2019-11-04 19:55:15
    最近在看数据库相关的三方库的时候,我发现在Android应用开发的时候是可以并行操作数据库的读写,但Android默认的数据连接池中只有一个数据库链接。一个数据库连接能实现并发么?要是一个数据库链接可以实现并发,...
  • 使用socket与多线程实现手机聊天功能,手机客户端的实现 刚开始会出来一个登录界面,需要我们输入账号,密码,如果没有,点击注册新账号,会跳转到注册页面。 注册好的用户会提交到服务器端,保存到数据库中。 登陆...
  • androrid android studio 后台接口 后台 服务 数据库 前端交互 post
  • 简单的使用Socket实现数据通信
  • 思路: 安卓客户端输入账号和密码,使用 okHttp 向服务器端发送请求并传递输入的账号和密码,... 服务器端: ...1. 数据库 2. 服务器端是 Java Web 用SpringBoot+Mybatis-Plus 快速搭建的,接口返回 map ...
  • 本文总结了Android客户端服务器进行交互时,采用RESTful API +Json的交互方式,针对不同的数据形式以及不同的解析方法,如有不足之处,欢迎指正。
  • 我在数据库里模拟了一些采集到的数据,下面具体讲服务器和手机端数据交互的过程,手机发送指令给服务器,具体查询过程交由服务器完成,再将查询结果返回到手机客户端,这里面涉及到知识点有数据库操作、socket通信、...
  • Android与MyEclipse的交互 2020-05-25 23:30:43
    简单的有服务器端客户端交互进行登录注册,数据库数据会自动增加
  • Android Studio 使用jdbc远程连接阿里云主机web数据库(逃坑) Tip1:主线程不能访问网络需要再写一个线程,访问web数据库。 Test 1 : 接下来开始配置一些东西: <uses-permission android:name="android....
  • $conn = mysql_connect("localhost", "root", "root"); ?> ... ... if($_POST['username']!=""&&$_POST['password']!... $sql="select * from 'user' where username='$_POST[username]'";... $sql2="insert into 'user'...
  • android前端怎样php后台交互(基础篇) android客户端和php+mysql+apache搭建的服务器之间的简单交互实现登入功能。 实现原理就是android客户端发送请求,传给服务器登入的用户名密码,服务器收到这些...
  • 无论前后端数据交互,还是安卓端和后端的数据交互都是一样的道理。最基础的发送json,解析json。 一、最先接触到就是okhttp,今天抽个时间来总结一下okhttp的使用吧。盗用一下网上的介绍(手动滑稽) okhttp简介:...
  • 1.Socket 通信简介及模型 Java Socket实现客户端–服务器间的双向实时通信。java.net包中定义的两个类socket和ServerSocket,分别用来实现双向连接的client和server端。通过Socket实现TCP编程1.1 TCP编程  ...
  • 学习TokenToken是什么?Token是服务端生成的一串字符串...Token的引入——Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样
  • android开发资料大全 2020-06-27 09:49:20
    Android数据库最基础的一个例子(本人已测试,可以运行) 为launcher添加一个仿Mac的dock(附源码) 使用Gallery实现Tab 仿QQ--tab切换动画实例 Android 小项目之---猜扑克牌游戏 (附源码) fleep滑动切换tab(切换...
  • 好久没更新了,罪过罪过。... 到【一步一个脚印】Tomcat+MySQL为自己的APP打造服务器(2-3)Servlet连接MySQL数据库为止,我们已经将服务端的部分走通了:通过 Servlet 连接 MySQL ,分析业务需求进行响
1 2 3 4 5 ... 20
收藏数 8,131
精华内容 3,252