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
- android基础之二——网络编程(二)
- Android基础之二——网络编程(一)
- 【Android基础】二、网络编程
- Android网络编程基础(二)
- Java基础—网络编程(二)
- 网络编程基础<二>
- Android之Http网络编程(二)
- Android开发之网络编程(二)
- 网络编程之二
- Android网络编程(二)
- 网络编程基础(二)——使用UDP
- Java基础——网络编程(二)
- Linux——网络编程基础(二)
- Linux网络编程基础(二)
- Linux网络编程基础二
- 网络编程基础(二)
- 黑马程序员---Java基础--24天(网络编程之二)
- Boost asio学习笔记之二—— 网络编程
- C#聊天程序基于HP-SOCKET V1.1最终版
- tiny4412下的Exynos4412 iROM 启动分析
- [Matlab]使用Simulink进行UDP通讯1
- 详解Android中AsyncTask的使用
- CSS 选择器 element.id 与element .id element.class 与 element .class
- android基础之二——网络编程(二)
- 安卓第二天笔记--数据保存
- Spinner
- 用Qt实现一个桌面弹幕程序(五)-- -- 桌面客户端实现①
- cvWaitKey
- 人民币符号的使用注意
- SpeedTree - 在SpeedTree中导入自定义模型
- android基础之一——android下的数据库
- 将U-Boot、uImage和rootfs烧入iMX53系统的4GB SD卡