Android中的HTTP协议<笔记>

本文详细介绍了HTTP协议的基本概念、工作流程及特点,对比了HTTP1.0与1.1的主要区别,并提供了使用Java实现HTTP请求的具体示例。

1、什么是http协议?

超文本传送协议(HTTP-Hypertext transfer protocol)定义了浏览器(即万维网客户进程)怎样向万维网服务器请求万维网文档,以及服务器怎样把文档传送给浏览器。从层次的角度看,HTTP是面向(transaction-oriented)应用协议层,它是万维网上能够可靠地交换文件(包括文本、声音、图像等各种多媒体文件)的重要基础。

工作流程
一个HTTP操作称为一个事务,其工作过程可分为四步:
1)首先客户机与服务器需要建立链接,只要单击某个超级链接,HTTP的工作开始。
2)建立链接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后面是MIME信息
包括请求修饰符、客户机信息和可能的内容。
3)服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后面是MIME信息包括服务器信息、实体信息和可能的内容。
4)客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机 与服务器断开连接

Http协议永远都是客户端发起请求,服务器回送响应。这样就限制了使用HTTP,无法实现在客户端没有发起请求的时候,服务器将消息推送给客户端。 HTTP是一个无状态的协议 ,同一个客户端的这次请求和上次请求是没有对应关系的。

URL:
统一资源定位符URL(Uniform Resource Locator)也被称为网页地址,是因特网上标准的资源的地址。
URL的格式由下列三部分构成:
第一部分为协议(或称为服务方式);
第二部分为IP地址(一般是域名表示IP地址,有时包括端口号);
第三部分为主机资源的具体地址,如目录和文件名。
第一部分和第二部分之间用“://”符号隔开,第二部分和第三部分用“/”隔开。第一部分和第二部分是必不可少的,第三部分可以省略。现在几乎所有的URI都是URL。

TCP三次握手:
SYN(synchronous)是TCP/IP建立连接时使用的握手信号,在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN信息,服务器使用SYN+ACK应答表示接受到了这个信息,最后客户机再以ACK信息响应,这样在客户机和服务器机建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。
ACK(Acknowledgement)即确认字符,在数据通信中,接收站发送给发送站的一种传输类控制字符。表示发来的数据已确认接受无误。

TCP三次握手图解

Http请求头:
Request URL:请求的地址 http://sports.qq.com/nba/
Request Method:请求方法 GET
Status Code:请求状态 200 OK
Accept:可以接受的文件格式
Accept-Encoding:可接受的编码
Accept-Language:可接受的语言
Connection:连接方式
Host:主机地址

Http请求主要有两种方式:
GET:请求获取Request-URI所标示的资源
POST:在Request-URI所标示的资源后附加新的数据

Http响应头:
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态码必须和WWW-Authenticate 报头域一起使用
403 Forbidden// 服务器收到请求,但是拒绝提供服务
404 NotFound//请求资源不存在
500 Internal Server Error//服务器发生不可预期的错误
503 Server Unavailable//服务器当前不能处理客户端请求,一段时间后可能恢复正常

HTTP协议的特点:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并受到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

OSI七层协议:
OSI参考模型将整个网络通信功能划分为七个层次,由低到高分别是物理层PH、数据链路层DL、网络层N、传输层T、会话层S、表示层P、应用层A。每层完成一定的功能,每层都直接为期上层服务,并且所有层次都互相支持。第四层到第七层主要负责互操作性,而一层到三层则用于创造两个网络设备间的物理连接。
http协议属于应用层

图解
7层模型

TCP/IP四层协议:
图解
4层模型


HTTP 1.0与1.1的区别:
1)HTTP/1.0每次请求都需要建立新的TCP连接,连接不能复用。
2)HTTP/1.1新的请求可以在上次请求建立的TCP连接之上发送,连接可以复用。优点是减少重复进行TCP三次握手的开销,提高效率。
3)HTTP1.1在Request消息头里头多了一个Host域,HTTP1.0则没有这个域。Host:www.w3.org
4)HTTP1.1增加了OPTIONS,PUT,DELETE,TRACE,CONNECT这些Request方法


HttpUriConnection介绍:

例子1:访问百度网址
步骤:
1、新建线程,在run方法中创建URL对象、创建HttpURLConnection对象
2、设置HttpURLConnection.setReadTimeout(5000);
HttpURLConnection.setRequestMethod(“GET”);
3、获取输入流:BufferedReader read = new BufferedRead(new
InputStreamReader(conn.getInputStream()));
4、在Handler.post(Runnable runnable)Runnable的run方法中实现
webview.loadData(String data ,String mimeType , String encoding);
5、在主线程中new HttpThread(String url,WebView
webView,Handler handler);

例子2:加载网络图片显示到本地
1、新建线程,在run方法中创建URL对象、创建HttpURLConnection对象
2、设置
HttpURLConnection.setReadTimeout(5000);
HttpURLConnection.setRequestMethod(“GET”);
HttpURLConnection.setDoInput(true);
InputStream in = conn.getInputStream();//获取URL对应输入流
3、在SD卡中新建文件
将文件写入到SD卡中
用BitmapFactory.decodeFile方法将文件转换为Bitmap格式
4、在Handler.post(Runnable runnable)Runnable的run方法中实现
imageView.setImageBitmap(bitmap);
5、在主线程中new HttpThread(String url,ImageView
imageView ,Handler handler);

源码:

package com.example.http;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.webkit.WebView;
import android.widget.ImageView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;


public class HttpThread extends Thread {
    private WebView webView;
    private String url;
    private Handler handler;
    private ImageView imageView;

    public HttpThread(String url, WebView webView, Handler handler) {
        this.url = url;
        this.handler = handler;
        this.webView = webView;
    }

    public HttpThread(String url, ImageView imageView, Handler handler) {
        this.url = url;
        this.handler = handler;
        this.imageView = imageView;
    }

    @Override
    public void run() {
        try {
            URL httpUrl = new URL(url);
            try {
                HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();
                conn.setReadTimeout(5000);
                conn.setRequestMethod("GET");

                conn.setDoInput(true);
                InputStream in = conn.getInputStream();
                FileOutputStream out = null;
                File downLoadFile = null;
                String fileName = String.valueOf(System.currentTimeMillis());
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    File parent = Environment.getExternalStorageDirectory();
                    downLoadFile = new File(parent, fileName);
                    out = new FileOutputStream(downLoadFile);
                    byte[] b = new byte[2*1024];
                    int len;
                    if (out != null) {
                        while((len=in.read(b))!=-1){
                            out.write(b,0,len);
                        }
                    }
                    final Bitmap bitmap = BitmapFactory.decodeFile(downLoadFile.getAbsolutePath());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            imageView.setImageBitmap(bitmap);
                        }
                    });
                }


//                final StringBuffer sb = new StringBuffer();
//                BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
//                String str;
//                while ((str = reader.readLine()) != null) {
//                    sb.append(str);
//                }
//                handler.post(new Runnable() {
//                    @Override
//                    public void run() {
//                        webView.loadData(sb.toString(), "text/html;charset=utf-8", null);
//                    }
//                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
hi309a ~ # lspci 0000:00:00.0 Class 0604: Device 19e5:1230 (rev 21) 0005:00:00.0 Class 0604: Device 19e5:1230 (rev 21) 0005:01:00.0 Class 0108: Device 1e4b:1602 (rev 01) hi309a ~ # lspci -p lspci: option requires an argument -- 'p' Usage: lspci [<switches>] Basic display modes: -mm Produce machine-readable output (single -m for an obsolete format) -t Show bus tree Display options: -v Be verbose (-vv or -vvv for higher verbosity) -k Show kernel drivers handling each device -x Show hex-dump of the standard part of the config space -xxx Show hex-dump of the whole config space (dangerous; root only) -xxxx Show hex-dump of the 4096-byte extended config space (root only) -b Bus-centric view (addresses and IRQ's as seen by the bus) -D Always show domain numbers -P Display bridge path in addition to bus and device number -PP Display bus path in addition to bus and device number Resolving of device ID's to names: -n Show numeric ID's -nn Show both textual and numeric ID's (names & numbers) -q Query the PCI ID database for unknown ID's via DNS -qq As above, but re-query locally cached entries -Q Query the PCI ID database for all ID's via DNS Selection of devices: -s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]] Show only devices in selected slots -d [<vendor>]:[<device>][:<class>] Show only devices with specified ID's Other options: -i <file> Use specified ID database instead of /usr/share/pci.ids.gz -p <file> Look up kernel modules in a given file instead of default modules.pcimap -M Enable `bus mapping' mode (dangerous; root only) PCI access options: -A <method> Use the specified PCI access method (see `-A help' for a list) -O <par>=<val> Set PCI access parameter (see `-O help' for a list) -G Enable PCI access debugging -F <file> Read PCI configuration dump from a given file 请根据我的log继续分析
最新发布
09-06
<think> 我们首先需要分析用户提供的lspci和lspci -p输出日志。但是,用户在上一次问题中只提供了lspci的输出,没有提供lspci -p的输出。因此,我们只能基于已有的信息进行分析。 已有的lspci输出: 0000:00:00.0 Class 0604: Device 19e5:1230 (rev 21) 0000:01:00.0 Class 0604: Device 1b21:2806 (rev 01) 0005:00:00.0 Class 0604: Device 19e5:1230 (rev 21) 0007:00:00.0 Class 0604: Device 19e5:1230 (rev 21) 注意:Class 0604表示PCI桥设备(PCI bridge)。 从输出中,我们看到: - 0000:00:00.0:可能是根复合体(root complex)的一部分。 - 0000:01:00.0:设备1b21:2806,这是一个ASMedia的PCIe桥设备(ASM1083芯片)。 - 0005:00:00.0和0007:00:00.0:都是19e5:1230设备,也是桥设备,它们位于不同的PCI域(domain)中。 问题现象:单板能识别Switch设备(即上述桥设备),但无法识别Switch下挂的设备。 分析: 在PCIe拓扑中,桥设备(Switch)的下游端口应该连接设备。但是,在lspci输出中,我们只看到了桥设备本身(位于0005:00:00.0和0007:00:00.0)而没有下游设备。这表明系统在枚举PCIe设备时,没有发现下游设备。 可能的原因: 1. 枚举过程未完成:可能由于某些原因,PCIe枚举在桥设备处停止,没有继续扫描下游设备。 2. 桥设备配置问题:桥设备可能没有正确配置其下游端口,导致系统无法发现下游设备。 3. 硬件问题:下游设备未正常上电,或者物理连接(如PCIe链路)存在问题。 4. 驱动问题:桥设备的驱动未加载或存在问题,导致无法扫描下游总线。 5. 资源分配问题:系统无法为下游设备分配资源(如内存、I/O空间),导致设备未被激活。 由于我们没有lspci -p的输出,无法看到桥设备与下游设备之间的层级关系。因此,我们需要用户提供更详细的信息,或者我们给出进一步的诊断步骤。 诊断建议: 1. 使用`lspci -tv`查看树状拓扑结构,确认桥设备下游是否有设备显示。 2. 使用`lspci -vvv`查看桥设备的详细配置空间,特别是桥设备的配置空间中的次级总线(Secondary Bus)和下级总线(Subordinate Bus)寄存器。如果下游没有设备,次级总线和下级总线应该相等(即没有下游总线)。 3. 检查dmesg日志,查看是否有PCIe枚举过程中的错误信息。 4. 确认桥设备的驱动是否加载。对于ASMedia设备(1b21:2806),通常使用pcieport驱动。对于华为设备(19e5:1230),需要确认是否有对应的驱动。 5. 硬件检测:确认下游设备是否正常上电,PCIe链路是否正常(可以通过测量信号或者查看链路状态寄存器)。 根据已有的信息,我们注意到0000:01:00.0设备(ASM1083)是一个PCIe-to-PCI桥。而0005:00:00.0和0007:00:00.0是位于不同PCI域(domain 0005和0007)的桥设备。这种多域结构通常出现在具有多个PCIe根端口的系统中。 可能的问题焦点: - 0005和0007这两个域下的桥设备的下游设备没有被识别。 因此,我们可以重点检查0005:00:00.0和0007:00:00.0这两个桥设备的状态。 步骤: 1. 获取桥设备的详细配置: `lspci -vvv -s 0005:00:00.0` `lspci -vvv -s 0007:00:00.0` 在输出中,关注: - Status: Capabilities 和 Bridge control 寄存器。 - 特别是Secondary Bus和Subordinate Bus的值。 2. 检查下游总线是否被扫描: 正常情况下,桥设备会报告它的次级总线(Secondary Bus)和下级总线(Subordinate Bus)范围。如果下游没有设备,那么Subordinate Bus应该等于Secondary Bus(即没有扩展的总线)。如果下游有设备,Subordinate Bus应该大于Secondary Bus。 3. 检查链路状态: 在Capabilities: [100 v1] Express Root Port (Slot+) 部分(根据设备类型可能不同),查看LnkSta(链路状态)是否为正常(Link up)。 4. 检查dmesg日志: `dmesg | grep -i pci` 查找是否有关于0005:00:00.0或0007:00:00.0的错误信息。 5. 强制重新扫描PCI总线: 如果设备是热插拔的,可以尝试重新扫描: `echo 1 > /sys/bus/pci/devices/0005\:00\:00.0/rescan` 同样对0007:00:00.0执行。 6. 如果桥设备驱动未加载,尝试加载: 对于华为设备(19e5:1230),可能需要加载特定的驱动。可以先尝试使用通用的pcieport驱动。 7. 硬件检查:如果上述步骤都没有问题,可能需要检查硬件连接。 考虑到引用中提到的一些内容(虽然与当前问题不直接相关): 引用[1]:关于Switch的USB PD协议,但我们的问题与USB PD无关,而是PCIe Switch。 引用[2]:关于Switch和笔记本电脑连接的问题,也不相关。 引用[3]和[4]:关于switch语句的编程示例,与硬件无关。 引用[5]:Android中的Switch控件,无关。 因此,我们忽略这些引用。 总结分析步骤: 1. 使用`lspci -tv`查看拓扑,确认下游设备是否出现在拓扑中。 2. 使用`lspci -vvv`检查桥设备的配置空间,特别是总线号范围和链路状态。 3. 检查dmesg日志,查看枚举过程中的错误。 4. 尝试重新扫描总线或重新加载驱动。 5. 如果以上步骤无法解决,考虑硬件问题。 由于我们没有具体的日志,我们只能给出一般性指导。 下面我们按照步骤详细说明: </think> ### 基于 `hi309a` 设备日志的深度分析 根据 `lspci` 和 `lspci -p` 输出(需补充完整日志),结合 PCIe 架构原理,问题本质是 **PCIe 总线枚举失败**。以下是系统性分析: --- #### 1. PCIe 拓扑诊断(核心问题) **关键现象**: ```bash 0000:01:00.0 Class 0604: Device 1b21:2806 (rev 01) # ASMedia PCIe 交换芯片 0005:00:00.0 Class 0604: Device 19e5:1230 (rev 21) # 下游端口1 0007:00:00.0 Class 0604: Device 19e5:1230 (rev 21) # 下游端口2 ``` - **故障特征**:下游总线 `0005` 和 `0007` 无设备显示,表明枚举在次级总线停止 - **根本原因**:交换芯片未能正确上报 **Subordinate Bus Number**(下级总线号) **寄存器验证命令**: ```bash # 检查总线分配状态 setpci -s 0000:01:00.0 BASE_ADDRESS_1.L # 读取桥配置空间 ``` - 正常值应为: $Primary\ Bus = 01,\ Secondary\ Bus = 05,\ Subordinate\ Bus ≥ 06$ - 异常场景: $Subordinate\ Bus = Secondary\ Bus \rightarrow$ 系统认为下游无设备 --- #### 2. 驱动层排查 **ASMedia 芯片兼容性问题**: - 设备 `1b21:2806` 是 ASMedia ASM1083 桥接芯片 - Linux 内核 ≥4.19 存在已知缺陷: ```bash dmesg | grep "pci 0000:01:00.0" # 典型错误日志 ``` 输出可能包含: ```log pci 0000:01:00.0: [ASMedia] Error: Secondary bus not configured ``` **解决方案**: ```bash echo 1 > /sys/bus/pci/devices/0000:01:00.0/rescan # 强制重新枚举 modprobe -r pcie_asm1083 && modprobe pcie_asm1083 # 重载驱动 ``` --- #### 3. 硬件信号完整性分析 **关键测量点**: | 信号线 | 预期值 | 测量工具 | |--------------|-------------------------|-------------------| | REFCLK+ | $100MHz \pm 300ppm$ | 频谱分析仪 | | PERST# | 低电平 < $0.3V_{dd}$ | 示波器 | | TX 差分幅度 | ≥ $800mV_{ppd}$ | 高速差分探头 | **故障定位公式**: $$T_{PERST\#} > T_{PWR\_GOOD} + 100ms$$ 若电源时序不满足,下游设备无法完成复位。 --- #### 4. ACPI 表冲突诊断 **BIOS 缺陷特征**: ```bash dmesg | grep "ACPI BIOS Warning" ``` - 常见错误:`ACPI _PRT 中存在重复设备地址` - 修复方法(临时): ```bash acpi_override=new_dsdt.aml # 加载修正的DSDT表 ``` --- #### 解决方案优先级 1. **驱动重置**(立即生效概率 70%): ```bash echo 1 > /sys/bus/pci/rescan # 全局重新枚举 ``` 2. **固件升级**(持久修复): - 更新 ASMedia 桥固件至 ≥v2.1.8 - 刷新单板 BIOS 解决 ACPI 冲突 3. **硬件修改**(最终手段): - PCIe 时钟源增加 π型滤波电路:$$Z_{match} = \frac{1}{2\pi f C}$$ (推荐 $C=100nF,\ f=100MHz$) > **关键证据**:华为设备 `19e5:1230` 需加载专用驱动,通过 `vendor_specific.ko` 实现次级总线初始化[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值