Http 网络协议 以及 文件上传下载(断点续传)

HTTP协议

HTTP协议(Hyper Text Transfer Protocol,超文本传输协议),是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。HTTP基于客户端/服务端(C/S)架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议。它是互联网上应用最为广泛的一种网络协议。HTTP是一种应用层协议,它是基于TCP/IP协议之上的请求/响应式的协议,即一个客户端与服务器建立连接后,向服务器发送一个请求;服务器接到请求后,给予相应的响应信息。

请求协议 响应协议

HTTP请求由请求行、请求头、请求体三部分组成:

1.请求行:包括请求方式Method、资源路径URL、协议版本Version;
①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。
②为请求对应的URL地址,它和报文头的Host属性组成完整的请求URL。
③是协议名称及版本号。

2.请求头:包括一些访问的域名、用户代理、Cookie等信息;
④是HTTP的报文头,报文头包含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。与缓存相关的规则信息,均包含在header中
首部字段名有如下:
Accept 指定客户端能够接收的内容格式类型
Accept-Language 指定客户端能够接受的语言类型
Accept-Ecoding 指定客户端能够接受的编码类型
User-Agent 用户代理,向服务器说明自己的操作系统、浏览器等信息
Connection 是否开启持久连接(keepalive)
Host 服务器域名

3.请求体:就是HTTP请求的数据。

get请求无请求体

HTTP响应由三部分组成:响应行、响应头、响应体

1.响应行:
①报文协议及版本;
②状态码及状态描述;

2.响应头:
③响应报文头,也是由多个属性组成;

首部字段名如下:
Server 服务器软件名,Apache/Nginx
Date 服务器发出响应报文的时间
Last-Modified 请求资源的最后的修改时间

3.响应体:
④响应报文体,即我们真正要的“干货”

响应状态码

HTTP的响应状态码由5部分组成:

1xx 消息,一般是告诉客户端,请求已经收到了,正在处理,别急…
2xx 处理成功,一般表示:请求收悉、我明白你要的、请求已受理、已经处理完成等信息.
3xx 重定向到其它地方。它让客户端再发起一个请求以完成整个处理。
4xx 处理发生错误,责任在客户端,如客户端的请求一个不存在的资源,客户端未被授权,禁止访问等。
5xx 处理发生错误,责任在服务端,如服务端抛出异常,路由出错,HTTP版本不支持等。

常见状态码及含义:

200—OK/请求已经正常处理完毕
301—/请求永久重定向
302—/请求临时重定向
304—/请求被重定向到客户端本地缓存
400—/客户端请求存在语法错误
401—/客户端请求没有经过授权
403—/客户端的请求被服务器拒绝,一般为客户端没有访问权限
404—/客户端请求的URL在服务端不存在
500—/服务端永久错误
503—/服务端发生临时错误

HTTP协议版本更替

HTTP/0.9
HTTP协议的最初版本,功能简陋,仅支持请求方式GET,并且仅能请求访问HTML格式的资源。

HTTP/1.0
在0.9版本上做了进步,增加了请求方式POST和HEAD;不再局限于0.9版本的HTML格式,根据Content-Type可以支持多种数据格式,即MIME多用途互联网邮件扩展,例如text/html、image/jpeg等;同时也开始支持cache,就是当客户端在规定时间内访问统一网站,直接访问cache即可。
但是1.0版本的工作方式是每次TCP连接只能发送一个请求,当服务器响应后就会关闭这次连接,下一个请求需要再次建立TCP连接,就是不支持keepalive。

HTTP/1.1
解决了1.0版本的keepalive问题,1.1版本加入了持久连接,一个TCP连接可以允许多个HTTP请求; 加入了管道机制,一个TCP连接同时允许多个请求同时发送,增加了并发性;新增了请求方式PUT、PATCH、DELETE等。
但是还存在一些问题,服务端是按队列顺序处理请求的,假如一个请求处理时间很长,则会导致后边的请求无法处理,这样就造成了队头阻塞的问题;同时HTTP是无状态的连接,因此每次请求都需要添加重复的字段,降低了带宽的利用率。

HTTP/2.0
为了解决1.1版本利用率不高的问题,提出了HTTP/2.0版本。增加双工模式,即不仅客户端能够同时发送多个请求,服务端也能同时处理多个请求,解决了队头堵塞的问题;HTTP请求和响应中,状态行和请求/响应头都是些信息字段,并没有真正的数据,因此在2.0版本中将所有的信息字段建立一张表,为表中的每个字段建立索引,客户端和服务端共同使用这个表,他们之间就以索引号来表示信息字段,这样就避免了1.0旧版本的重复繁琐的字段,并以压缩的方式传输,提高利用率。
另外也增加服务器推送的功能,即不经请求服务端主动向客户端发送数据。
当前主流的协议版本还是HTTP/1.1版本。

1.get请求和post请求的区别
get请求直接将请求参数暴露在url,不安全+一般用于向服务器请求数据
post请求将请求参数放在请求体里面,安全的+一般用于向服务器提交数据

2.网络七层
应用层:应用程序,用户看的见 http协议
表示层:将人看的懂的转成计算机看的懂
会话层:发起一个连接
传输层:规定传输协议和端口号 tcp协议 udp协议
网络层:规定网络ip ip协议
数据链路层:
物理层:光缆、网线

3.8种请求方式:
1、OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
2、HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
3、GET
向特定的资源发出请求。它本质就是发送一个请求来取得服务器上的某一资源。资源通过一组HTTP头和呈现数据(如HTML文本,或者图片或者视频等)返回给客户端。
4、POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。
5、PUT
向指定资源位置上传其最新内容
6、DELETE
请求服务器删除Request-URL所标识的资源
7、TRACE
回显服务器收到的请求,主要用于测试或诊断
8、CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

文件上传和下载

上传文件:post请求
1.设置请求头信息:
Content-Length:请求体的长度
Content-Type:multipart/form-data; boundary=7e324741816d4(随便)
2.请求体:2部分
第一部分:要有换行
-----------------------------7e324741816d4(一上面随便的一模一样)
Content-Disposition: form-data; name=“file”; filename=“上传到服务器的名字”
Content-Type: media/mp4或者media/mp3或者image/jpeg或者image/png
空行

上传 代码 (线程)

package com.example.download;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class shangchuan extends AppCompatActivity {
Button button;
String url="http://169.254.113.244/1705hfs/";
String filname="axiba.jpg";
String path="/sdcard/zha.jpg";

@SuppressLint("HandlerLeak")
Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (msg.what==101){
            Toast.makeText(shangchuan.this, "完事儿", Toast.LENGTH_SHORT).show();
        }
    }
};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shangchuan);
        button=findViewById(R.id.shangchuan);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
new shanchuan(url,filname,path,handler).start();
            }
        });
    }
    class shanchuan extends Thread{
        String url;
        String filname;
        String path;
      Handler handler;

        public shanchuan(String url, String filname, String path, Handler handler) {
            this.url = url;
            this.filname = filname;
            this.path = path;
            this.handler = handler;
        }

        @Override
        public void run() {
            super.run();
            URL url1 = null;
            try {
                url1 = new URL(url);
                HttpURLConnection urlConnection = (HttpURLConnection) url1.openConnection();
                StringBuffer sb = new StringBuffer();
                sb.append("-----------------------------7e324741816d4"+"\r\n");
                sb.append("Content-Disposition: form-data; name=\"file\"; filename=\""+filname+"\""+"\r\n");
                sb.append("Content-Type: media/jpg" + "\r\n");
                sb.append("\r\n");
                byte[]  bytes = sb.toString().getBytes("UTF-8");
                urlConnection.setRequestProperty("Content-Length",bytes.length+new File(path).length()+"");
                urlConnection.setRequestProperty("Content-Type","multipart/form-data; boundary=7e324741816d4");
                urlConnection.setRequestMethod("POST");
                urlConnection.setDoOutput(true);
                OutputStream outputStream = urlConnection.getOutputStream();
                FileInputStream fileInputStream = new FileInputStream(path);
                outputStream.write(bytes);
                byte[] bytes1=new byte[1024];
                int len=0;
                while((len=fileInputStream.read(bytes1))!=-1){
                    outputStream.write(bytes1,0,len);
                }
                if (urlConnection.getResponseCode() == 200) {
                    handler.sendEmptyMessage(101);
                }
            } catch (MalformedURLException e) {
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

下载(线程)

package com.example.download;

import android.os.Handler;
import android.os.Message;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;


public class DownLoadThread  extends Thread{
    private String str_url;
    private String path;
    private Handler handler;

    public DownLoadThread(String str_url, String path, Handler handler) {
        this.str_url = str_url;
        this.path = path;
        this.handler = handler;
    }

    @Override
    public void run() {
        super.run();
        try {
            URL url=new URL(str_url);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setReadTimeout(5*1000);
            urlConnection.setConnectTimeout(5*1000);
            urlConnection.connect();
            if(urlConnection.getResponseCode()==200){

                int max = urlConnection.getContentLength();
                Message message = Message.obtain();
                message.what= MainActivity.BAR_MAX;
                message.obj=max;
                handler.sendMessage(message);
                InputStream inputStream = urlConnection.getInputStream();
                FileOutputStream fileOutputStream = new FileOutputStream(path);
                byte[] bytes=new byte[1024];
                int len=0;
                int count=0;
                while ((len=inputStream.read(bytes))!=-1){
                    fileOutputStream.write(bytes,0,len);
                    count+=len;
                    Message message1 = Message.obtain();
                    message1.what=MainActivity.BAR_CURRENT;
                    message1.obj=count;
                    handler.sendMessage(message1);
                }
                handler.sendEmptyMessage(103);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}

断点续传

请求两次 将文件大小进行判断

是否存在 如果文件大小等于待请求文件大小 不请求

文件不全 将文件大小作为第二次请求开始位置 断点续传 使用随机访问流

package com.example.download;

import android.os.Handler;
import android.os.Message;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class DuandianThread extends Thread {
    private String str_url;
    private String path;
    private Handler handler;

    public DuandianThread(String str_url, String path, Handler handler) {
        this.str_url = str_url;
        this.path = path;
        this.handler = handler;
    }

    @Override
    public void run() {
        super.run();
        int end = 0;
        int start = 0;
        try {
            URL url = new URL(str_url);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            if (urlConnection.getResponseCode() == 200) {
                end = urlConnection.getContentLength();
            }
            Message obtain = Message.obtain();
            obtain.what = 101;
            obtain.obj = end;
            handler.sendMessage(obtain);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            URL url = new URL(str_url);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

            File file = new File(path);
            if(file.exists()){
                start= (int) file.length();
                if(start==end){

                    handler.sendEmptyMessage(104);
                }
            }
            urlConnection.setRequestProperty("Range","bytes="+start+"-"+end);
            if(urlConnection.getResponseCode()==206){
                InputStream inputStream = urlConnection.getInputStream();

                RandomAccessFile randomAccessFile=  new RandomAccessFile(path,"rw");//rw 可读可写
                randomAccessFile.seek(start);

                byte[] bytes=new byte[1024];
                int len=0;
                int count=start;
                while((len=inputStream.read(bytes))!=-1){
                    randomAccessFile.write(bytes,0,len);
                    Thread.sleep(10);
                    count+=len;
                    Message obtain = Message.obtain();
                    obtain.what=102;
                    obtain.obj=count;
                    handler.sendMessage(obtain);
                    if(count==end){
                        handler.sendEmptyMessage(103);
                    }
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

你可能感兴趣的:(Http 网络协议 以及 文件上传下载(断点续传))