android基础之二——网络编程(二)

来源:互联网 发布:二叉树层次遍历 python 编辑:程序博客网 时间:2024/05/17 09:37

01_post方式提交数据的中文乱码解决

解决办法:保证客户端和服务器端使用的字符集编码一致。

    Tomcat默认的字符集编码是iso-8859-1,默认是iso-8859-1进行转码    String username = request.getParameter("username");     String password = request.getParameter("password");    Tomcat默认的字符集编码是iso-8859-1,默认是iso-8859-1进行转码,当它发现使用iso-8859-1不能编码中文的时候,会使用操作系统使用的本地码表(字符集编码)进行编码,所以我们需要自己编码response.getOutputStream().write("登陆成功".getBytes("UTF-8"));

02_get提交数据乱码的解决

04_使用HttpClient向服务器端提交数据

HttpClient : apache子项目

HttpClient 轻量级的浏览器

步骤:

   1、创建一个浏览器   2、输入一个网址   3、按回车

模版代码GET方式:

                    //1、创建一个浏览器                     HttpClient client = new DefaultHttpClient();                     //2、输入一个网址                     HttpGet httpGet = new HttpGet(path);                    //3、按回车                     HttpResponse response = client.execute(httpGet);                    //4、获取服务器端返回的响应数据,判断响应码,200ok,404找不到资源、503服务器内部错误,然后获取输入流;                    int code = response.getStatusLine().getStatusCode();                    if(code == 200){                        //获取返回的二进制数据流                        InputStream is = response.getEntity().getContent();

模版代码POST方式:

                    //1、创建一个浏览器                     HttpClient client = new DefaultHttpClient();                    // 2、输入一个网址                     HttpPost httpPost = new HttpPost(path);                     //封装提交的数据                     //类似map的数据结构                     BasicNameValuePair username = new BasicNameValuePair("username", qq);                     BasicNameValuePair password = new BasicNameValuePair("password", pwd);                     List<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>();                     list.add(username);                     list.add(password);                     //默认是使用iso-8859-1转码的                     UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,"UTF-8");                    httpPost.setEntity(entity);                    //3、按回车                     HttpResponse response = client.execute(httpPost);                    //4、获取服务器端返回的响应数据,判断响应码,200ok,404找不到资源、503服务器内部错误,然后获取输入流;                    int code = response.getStatusLine().getStatusCode();                    if(code == 200){                    //获取返回的二进制数据流                    InputStream is = response.getEntity().getContent();

05使用开源项目Asynchttpclient的GETPOST访问网络

  • 使用GET方式发送请求:

    public void login(View view){    String qq = et_qq.getText().toString().trim();    String pwd = et_pwd.getText().toString().trim();    try {        path = "http://192.168.13.41:8080/web/servlet/LoginServlet?username="+URLEncoder.encode(qq,"UTF-8")+"&password="+URLEncoder.encode(pwd, "UTF-8");        AsyncHttpClient client = new AsyncHttpClient();        client.get(path, new AsyncHttpResponseHandler() {            /**             * 请求成功,服务器端正常响应调用这个方法             * statusCode 响应码             * headers 响应头信息             *              * responseBody 服务器端返回的数据实体的字节数组             */            @Override            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {                Toast.makeText(MainActivity.this, new String(responseBody), 0).show();           }            /**             * 请求成功,服务器端正常响应调用这个方法             * statusCode 响应码             * headers 响应头信息             * responseBody 服务器端返回的数据实体的字节数组             * error 服务器端抛出来的异常信息              */            @Override            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {                Toast.makeText(MainActivity.this, "处理失败;"+new String(responseBody), 0).show();            }        });    } catch (Exception e) {        e.printStackTrace();    }

    }

  • 使用POST方式发送请求:

    path = "http://192.168.13.41:8080/web/servlet/LoginServlet";            //1、创建一个浏览器            AsyncHttpClient client = new AsyncHttpClient();        //2、设置参数        RequestParams params = new RequestParams();        params.put("username", qq);        params.put("password", pwd);        //3、发送请求        client.post(path, params, new AsyncHttpResponseHandler() {            /**             * 请求成功,服务器端正常响应调用这个方法             * statusCode 响应码             * headers 响应头信息             *              * responseBody 服务器端返回的数据实体的字节数组             */            @Override            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {                Toast.makeText(MainActivity.this, new String(responseBody), 0).show();           }            /**             * 请求成功,服务器端正常响应调用这个方法             * statusCode 响应码             * headers 响应头信息             * responseBody 服务器端返回的数据实体的字节数组             * error 服务器端抛出来的异常信息              */            @Override            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {                Toast.makeText(MainActivity.this, "处理失败;"+new String(responseBody), 0).show();            }        });

06_上传文件

代码:

        AsyncHttpClient client = new AsyncHttpClient();        RequestParams params = new RequestParams();        File file = new File(path);        //创建一个文件,作为一个参数提交给服务器端        params.put("file", file);        client.post("http://192.168.13.41:8080/web/servlet/UploadServlet", params, new AsyncHttpResponseHandler() {            @Override            public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {                Toast.makeText(MainActivity.this,   new String(arg2), 0).show();            }            @Override            public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {                Toast.makeText(MainActivity.this,   "处理失败;", 0).show();                arg3.printStackTrace();            }        });

07_多线程加速下载的原理

08_多线程下载的原理

需要解决问题:1、在客户端创建一个与服务器端一样大小的空文件:content-length;RandomAccessFile2、根据线程的个数等分文件,计算出每个线程下载的数据块大小:length/threadcount=blocksize3、计算每个子线程下载数据的开始位置和结束位置:   开始位置:threadid*blocksize 结束位置:(threadid+1)*blocksize-1   最后一个子线程的开始为位置:threadid*blocksize ,结束位置:length-14、确定每个子线程从什么开始写数据:seek()5、创建子线程,开始下载数据;6、确定每个子线程都下载完毕,以此来确定每个文件下载完成;

09_javase多线程下载的逻辑

代码:MultiThreadDownLoader.java

package com.itheima;import java.io.File;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;public class MultiThreadDownLoader {private static int threadCount = 3;public static void main(String[] args) {    try {        String path = "http://192.168.13.41:8080/sogou.exe";        URL url = new URL(path);        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        conn.setRequestMethod("GET");        conn.setConnectTimeout(3000);        int code = conn.getResponseCode();        if(code == 200){        //1、在客户端创建一个与服务器端一样大小的空文件:content-length;RandomAccessFile        int length = conn.getContentLength();        File file = new File("temp.exe");        RandomAccessFile raf = new RandomAccessFile(file, "rw");        raf.setLength(length);//           2、根据线程的个数等分文件,计算出每个线程下载的数据块大小:length/threadcount=blocksize        int blockSize = length/threadCount;//          3、计算每个子线程下载数据的开始位置和结束位置://             开始位置:threadid*blocksize 结束位置:(threadid+1)*blocksize-1//             最后一个子线程的开始为位置:threadid*blocksize ,结束位置:length-1        for(int threadId=0; threadId<threadCount; threadId++){            //开始位置            int startIndex = threadId * blockSize;            //结束位置            int endIndex = (threadId+1)*blockSize-1;            //最后一个线程下载的结束位置            if(threadId==threadCount-1){                endIndex =  length-1;            }//              4、确定每个子线程从什么开始写数据:seek()//              5、创建子线程,开始下载数据;           new ChildThreadDownLoader(startIndex,endIndex,threadId,path).start();        }//                            }    } catch (Exception e) {        e.printStackTrace();    }}}

子线程下载:ChildThreadDownLoader.java

package com.itheima;import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.ProtocolException;import java.net.URL;public class ChildThreadDownLoader extends Thread {private static int runningThreadCount = 3;private int startIndex;private int endIndex;private int threadId;private String path;public ChildThreadDownLoader(int startIndex, int endIndex, int threadId,        String path) {    this.startIndex = startIndex;    this.endIndex = endIndex;    this.threadId = threadId;    this.path = path;}  @Overridepublic void run() {    try {        URL url = new URL(path);        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        conn.setRequestMethod("GET");        conn.setConnectTimeout(3000);        //设置请求数据的数范围 bytes=0-3        conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);        int code = conn.getResponseCode();        //成功返回部分数据code=206 200表示返回全部数据        if(code == 206){        //1、在客户端创建一个与服务器端一样大小的空文件:content-length;RandomAccessFile        InputStream is = conn.getInputStream();        File file = new File("temp.exe");        RandomAccessFile raf = new RandomAccessFile(file, "rwd");        System.out.println("线程"+threadId+"开始下载:"+startIndex+","+endIndex);//          4、确定每个子线程从什么开始写数据:seek()        raf.seek(startIndex);        //开始下载数据        byte[] buffer = new byte[1024*20];        int len = -1;        while((len = is.read(buffer)) != -1){            raf.write(buffer, 0, len);        }        is.close();        raf.close();        System.out.println("线程"+threadId+"下载完成..............");        //6、确定每个子线程都下载完毕,以此来确定每个文件下载完成;        synchronized (ChildThreadDownLoader.class) {            runningThreadCount--;            if(runningThreadCount == 0){                System.out.println("文件下载完毕........................");            }        }}    } catch (Exception e) {        e.printStackTrace();    }}}

10_javase多线程断点下载

1、知道每个子线程上次下载到了什么位置

实时的记录每个子线程下载到的位置,写到一个文件里;

2、获取没格子线程上次下载到的位置,下次下载时接着上一次下载:

读取文件,得到上次下载到的位置,接着下载;

代码:

package com.itheima;import java.io.BufferedReader;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.ProtocolException;import java.net.URL;public class ChildThreadDownLoader extends Thread {private static int runningThreadCount = 3;private int startIndex;private int endIndex;private int threadId;private String path;public ChildThreadDownLoader(int startIndex, int endIndex, int threadId,        String path) {    this.startIndex = startIndex;    this.endIndex = endIndex;    this.threadId = threadId;    this.path = path;}  @Overridepublic void run() {    try {        URL url = new URL(path);        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        conn.setRequestMethod("GET");        conn.setConnectTimeout(3000);        //2、获取没格子线程上次下载到的位置,下次下载时接着上一次下载:读取文件,得到上次下载到的位置,接着下载;        File info = new File(threadId+".txt");        if(info.exists() && info.length()>0){            FileReader fr = new FileReader(info);            BufferedReader br = new BufferedReader(fr);            String lastDownPosition = br.readLine();            startIndex = Integer.valueOf(lastDownPosition);        }        //设置请求数据的数范围 bytes=0-3        conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);        int code = conn.getResponseCode();        //成功返回部分数据code=206 200表示返回全部数据        if(code == 206){        //1、在客户端创建一个与服务器端一样大小的空文件:content-length;RandomAccessFile        InputStream is = conn.getInputStream();        File file = new File("temp.exe");        RandomAccessFile raf = new RandomAccessFile(file, "rwd");        System.out.println("线程"+threadId+"开始下载:"+startIndex+","+endIndex);//          4、确定每个子线程从什么开始写数据:seek()        raf.seek(startIndex);        //开始下载数据        byte[] buffer = new byte[1024*20];        int len = -1;        int total=0;        while((len = is.read(buffer)) != -1){            raf.write(buffer, 0, len);            //把当前下载到的位置记录到文件里            total = total + len;            int currentPosition = startIndex + total;            RandomAccessFile f = new RandomAccessFile(threadId+".txt","rwd");            f.write((currentPosition+"").getBytes());            f.close();        }        is.close();        raf.close();        System.out.println("线程"+threadId+"下载完成..............");        //6、确定每个子线程都下载完毕,以此来确定每个文件下载完成;        synchronized (ChildThreadDownLoader.class) {            runningThreadCount--;            if(runningThreadCount == 0){                System.out.println("文件下载完毕........................");            }        }}    } catch (Exception e) {        e.printStackTrace();    }}}

11_多线程下载的Android移植

12_开目实现多线程下载

  • 示例代码:

    HttpUtils http = new HttpUtils();    HttpHandler handler = http.download(path,    Environment.getExternalStorageDirectory()+"/sogou.exe",        true, // 如果目标文件存在,接着未完成的部分继续下载。服务器不支持RANGE时将从新下载。        true, // 如果从请求返回信息中获取到文件名,下载完成后自动重命名。        new RequestCallBack<File>() {            @Override            public void onStart() {                tv_start.setText("conn...");            }            @Override            public void onLoading(long total, long current, boolean isUploading) {                tv_progress.setText(current + "/" + total);            }            @Override            public void onSuccess(ResponseInfo<File> responseInfo) {                Toast.makeText(MainActivity.this, "下载完成,文件在"+responseInfo.result.getPath(), 0).show();            }            @Override            public void onFailure(HttpException error, String msg) {                Toast.makeText(MainActivity.this, "下载失败", 0).show();                error.printStackTrace();            }    });
0 0
原创粉丝点击