123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta http-equiv="Content-Style-Type" content="text/css" />
- <meta name="generator" content="pandoc" />
- <title></title>
- <style type="text/css">code{white-space: pre;}</style>
- <style type="text/css">
- div.sourceCode { overflow-x: auto; }
- table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
- margin: 0; padding: 0; vertical-align: baseline; border: none; }
- table.sourceCode { width: 100%; line-height: 100%; }
- td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
- td.sourceCode { padding-left: 5px; }
- code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
- code > span.dt { color: #902000; } /* DataType */
- code > span.dv { color: #40a070; } /* DecVal */
- code > span.bn { color: #40a070; } /* BaseN */
- code > span.fl { color: #40a070; } /* Float */
- code > span.ch { color: #4070a0; } /* Char */
- code > span.st { color: #4070a0; } /* String */
- code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
- code > span.ot { color: #007020; } /* Other */
- code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
- code > span.fu { color: #06287e; } /* Function */
- code > span.er { color: #ff0000; font-weight: bold; } /* Error */
- code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
- code > span.cn { color: #880000; } /* Constant */
- code > span.sc { color: #4070a0; } /* SpecialChar */
- code > span.vs { color: #4070a0; } /* VerbatimString */
- code > span.ss { color: #bb6688; } /* SpecialString */
- code > span.im { } /* Import */
- code > span.va { color: #19177c; } /* Variable */
- code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
- code > span.op { color: #666666; } /* Operator */
- code > span.bu { } /* BuiltIn */
- code > span.ex { } /* Extension */
- code > span.pp { color: #bc7a00; } /* Preprocessor */
- code > span.at { color: #7d9029; } /* Attribute */
- code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
- code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
- code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
- code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
- </style>
- <link rel="stylesheet" href="css/vendor.css" type="text/css" />
- </head>
- <body>
- <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wb="http://open.weibo.com/wb" >
- <head>
- <title>一步步搭建物联网系统(教你设计物联网系统)</title>
- <meta name="keywords" content="设计物联网系统,物联网系统设计">
- <meta name="description" content="一份关于如何设计物联网系统的文档">
- <link rel="stylesheet" href="../css/vendor.css" />
- </head>
- <body class="container inner wrap">
- <h1>一步步搭建物联网系统(教你设计物联网系统)</h1>
- </body>
- </html>
- <div id="TOC">
- <ul>
- <li><a href="#http-熟悉陌生"><span class="toc-section-number">1</span> HTTP 熟悉&陌生</a><ul>
- <li><a href="#你所没有深入的http"><span class="toc-section-number">1.1</span> 你所没有深入的HTTP</a><ul>
- <li><a href="#打开网页时发生了什么"><span class="toc-section-number">1.1.1</span> 打开网页时发生了什么</a></li>
- <li><a href="#url组成"><span class="toc-section-number">1.1.2</span> URL组成</a></li>
- </ul></li>
- <li><a href="#一次http-get请求"><span class="toc-section-number">1.2</span> 一次HTTP GET请求</a><ul>
- <li><a href="#http响应"><span class="toc-section-number">1.2.1</span> HTTP响应</a></li>
- </ul></li>
- </ul></li>
- </ul>
- </div>
- <h1 id="http-熟悉陌生"><span class="header-section-number">1</span> HTTP 熟悉&陌生</h1>
- <h2 id="你所没有深入的http"><span class="header-section-number">1.1</span> 你所没有深入的HTTP</h2>
- <p>Internet有两个核心协议: IP和TCP,这样讲述起来似乎会很漫长。</p>
- <p>基本概念</p>
- <blockquote>
- <p>超文本传输协议 (HTTP-Hypertext transfer protocol) 是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。</p>
- </blockquote>
- <ul>
- <li>HTTP是用于客户端与服务端之间的通信。</li>
- <li>传输层的TCP是基于网络层的IP协议的,而应用层的HTTP协议又是基于传输层的TCP协议的。</li>
- </ul>
- <p><code>注意</code>: HTTP协议只规定了客户端与服务端的通信规则,而没有规定其通讯协议,只是现在的大部分实现都是将TCP作为通讯协议。</p>
- <h3 id="打开网页时发生了什么"><span class="header-section-number">1.1.1</span> 打开网页时发生了什么</h3>
- <p>简单地来说,当我们在浏览器上输入URL的敲下回车的时候。</p>
- <ul>
- <li>浏览器需要查找域名<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>的IP,从不同的缓存直至DNS服务器。</li>
- <li>浏览器会给web服务器发送一个HTTP请求</li>
- <li>服务器“处理”请求</li>
- <li>服务器发回一个HTML响应</li>
- <li>浏览器渲染HTML到页面。</li>
- </ul>
- <p>在<a href="http://stackoverflow.com/questions/2092527/what-happens-when-you-type-in-a-url-in-browser">StackOverflow</a>上有一个这样的回答会比较详细。</p>
- <ul>
- <li>browser checks cache; if requested object is in cache and is fresh, skip to #9</li>
- <li>browser asks OS for server’s IP address</li>
- <li>OS makes a DNS lookup and replies the IP address to the browser</li>
- <li>browser opens a TCP connection to server (this step is much more complex with HTTPS)</li>
- <li>browser sends the HTTP request through TCP connection</li>
- <li>browser receives HTTP response and may close the TCP connection, or reuse it for another request</li>
- <li>browser checks if the response is a redirect (3xx result status codes), authorization request (401), error (4xx and 5xx), etc.; these are handled differently from normal responses (2xx)</li>
- <li>if cacheable, response is stored in cache</li>
- <li>browser decodes response (e.g. if it’s gzipped)</li>
- <li>browser determines what to do with response (e.g. is it a HTML page, is it an image, is it a sound clip?)</li>
- <li>browser renders response, or offers a download dialog for unrecognized types</li>
- </ul>
- <p>忽略一些细节便剩下了</p>
- <ol style="list-style-type: decimal">
- <li>从浏览器输入URL</li>
- <li>浏览器找到服务器,服务器返回HTML文档</li>
- <li>从对应的服务器下载资源</li>
- </ol>
- <p>说说第一步,开始时我们输入的是URI(统一资源标识符,Uniform Resource Identifier),它还有另外一个名字叫统一资源定位器(URL<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a>,Uniform Resource Locator)。</p>
- <h3 id="url组成"><span class="header-section-number">1.1.2</span> URL组成</h3>
- <p>网址算是URL的一个俗称,让我们来看看一个URL的组成,以HTTP版IOT中的URL为例。</p>
- <p><code>http://b.phodal.com/athome/1</code></p>
- <p>开始之前,我们需要标出URL的80端口以及json文件的全称,那么上面的网址就会变成</p>
- <p><code>http://b.phodal.com:80/athome/1.json</code></p>
- <p>那么对于这个URL的就有下面几部分组成</p>
- <ul>
- <li><code>http://</code> http说的是这个URL用的是HTTP协议,至于<code>//</code>是一个分隔符,用法和C语言中的<code>;</code>一样。这样的协议还可以是coap,https,ftp等等。</li>
- <li><code>b</code> 是子域名,一个域名在<strong>允许</strong>的情况下可以有不限数量的子域名。</li>
- <li><code>phodal.com</code> 代表了一个URL是phodal.com下面的域名</li>
- <li><code>80</code> 80是指80端口,默认的都是80,对于一个不是80端口的URL应该是这样的<code>http://iot-coap.phodal.com:8896/</code></li>
- <li><code>athome</code> 指的是虚拟目录部分,或者文件路径</li>
- <li><code>1.json</code>看上去就是一个文件名,然而也代表着这是一个资源。</li>
- </ul>
- <p>对就一个稍微复杂点的例子就是</p>
- <p><code>http://ebook.designiot.cn/#你所没有深入的http</code></p>
- <p>这里的<code>#</code>后面是锚部分,如果你打开这个URL就会发现会直接跳转到相应的锚部分,对就于下面这样的一个例子来说</p>
- <p><code>http://www.phodal.com/search/?q=iot&type=blog</code></p>
- <p><code>?</code>后面的<code>q=iot&type=blog</code>的部分是参数部分,通常用于查询或者、搜索。</p>
- <h2 id="一次http-get请求"><span class="header-section-number">1.2</span> 一次HTTP GET请求</h2>
- <p>当我们打开最小物联网系统的一个页面时,如<a href="http://b.phodal.com/athome/1.json" class="uri">http://b.phodal.com/athome/1.json</a></p>
- <p>我们在浏览器上看到的结果是</p>
- <div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript">[
- <span class="op">{</span>
- <span class="st">"id"</span><span class="op">:</span> <span class="dv">1</span><span class="op">,</span>
- <span class="st">"temperature"</span><span class="op">:</span> <span class="dv">19</span><span class="op">,</span>
- <span class="st">"sensors1"</span><span class="op">:</span> <span class="dv">31</span><span class="op">,</span>
- <span class="st">"sensors2"</span><span class="op">:</span> <span class="fl">7.5</span><span class="op">,</span>
- <span class="st">"led1"</span><span class="op">:</span> <span class="dv">0</span>
- <span class="op">}</span>
- ]</code></pre></div>
- <p>只是我们看到的是结果,忽略了这其中的过程,于是我们用curl<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a>命令来看看详细的情况。</p>
- <div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">curl</span> -I -s http://b.phodal.com/athome/1.json</code></pre></div>
- <p>出于某种原因考虑,删去了其中一些元素,剩下下面这些。</p>
- <div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">HTTP/1.1</span> 200 OK
- <span class="kw">Content-Type</span>: application/json
- <span class="kw">Date</span>: Fri, 05 Sep 2014 15:05:49 GMT
- [<span class="dt">{"id":1,"temperature":19,"sensors1":31,"sensors2":7.5,"led1":0}</span>]</code></pre></div>
- <p>我们用curl命令向服务器发起了GET请求,服务器返回了上面的结果。</p>
- <h3 id="http响应"><span class="header-section-number">1.2.1</span> HTTP响应</h3>
- <p>一个HTTP响应由三部分组成</p>
- <ul>
- <li>状态行(状态码)</li>
- <li>消息报头(响应报头)</li>
- <li>响应正文(消息体)</li>
- </ul>
- <h4 id="http响应-状态码"><span class="header-section-number">1.2.1.1</span> HTTP响应 状态码</h4>
- <p>在上面的结果中,状态行是</p>
- <div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">HTTP/1.1</span> 200 OK</code></pre></div>
- <p>返回的状态码是200,OK是状态码的原因短语。</p>
- <p>如果是一个跳转的页面,它就可能是下面的结果:</p>
- <div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">HTTP/1.0</span> 301 MOVED PERMANENTLY
- <span class="kw">Date</span>: Mon, 08 Sep 2014 12:04:01 GMT
- <span class="kw">Content-Type</span>: text/html<span class="kw">;</span> <span class="ot">charset=</span>utf-8 </code></pre></div>
- <p>HTTP Status有五种状态,而这五种状态又有所细分,提一下这五种状态,详细可参见<a href="http://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81">http://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81</a></p>
- <ul>
- <li>1xx消息</li>
- <li>2xx成功</li>
- <li>3xx重定向</li>
- <li>4xx客户端错误</li>
- <li>5xx服务器错误</li>
- </ul>
- <p>如</p>
- <ul>
- <li>200 ok - 成功返回状态,对应,GET,PUT,PATCH,DELETE.</li>
- <li>201 created - 成功创建。</li>
- <li>304 not modified - HTTP缓存有效。</li>
- <li>400 bad request - 请求格式错误。</li>
- <li>401 unauthorized - 未授权。</li>
- <li>403 forbidden - 鉴权成功,但是该用户没有权限。</li>
- <li>404 not found - 请求的资源不存在</li>
- <li>405 method not allowed - 该http方法不被允许。</li>
- <li>410 gone - 这个url对应的资源现在不可用。</li>
- <li>415 unsupported media type - 请求类型错误。</li>
- <li>422 unprocessable entity - 校验错误时用。</li>
- <li>429 too many request - 请求过多。</li>
- </ul>
- <h4 id="http响应-响应报头"><span class="header-section-number">1.2.1.2</span> HTTP响应 响应报头</h4>
- <p>在这次响应中,返回了两个报头,即</p>
- <div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">Content-Type</span>: application/json
- <span class="kw">Date</span>: Fri, 05 Sep 2014 15:05:49 GMT</code></pre></div>
- <p>Content-Type和Date,在这里的Context-Type是application/json,而通常情况下我们打开一个网站时,他的Content-Type应该是text/html。</p>
- <div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">Content-Type</span>: text/html<span class="kw">;</span></code></pre></div>
- <p>Content-Type是最重要的报头。</p>
- <h4 id="http响应-响应正文"><span class="header-section-number">1.2.1.3</span> HTTP响应 响应正文</h4>
- <p>正文才是我们真正想要的内容,上面的都是写给浏览器看的,一般的人不会去关注这些。</p>
- <div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript">HTTP/<span class="fl">1.1</span> <span class="dv">200</span> OK
- Server<span class="op">:</span> <span class="va">phodal</span>.<span class="at">com</span>/<span class="fl">0.17.5</span>
- Content<span class="op">-</span>Type<span class="op">:</span> application/json
- [<span class="op">{</span><span class="st">"id"</span><span class="op">:</span><span class="dv">1</span><span class="op">,</span><span class="st">"temperature"</span><span class="op">:</span><span class="dv">19</span><span class="op">,</span><span class="st">"sensors1"</span><span class="op">:</span><span class="dv">31</span><span class="op">,</span><span class="st">"sensors2"</span><span class="op">:</span><span class="fl">7.5</span><span class="op">,</span><span class="st">"led1"</span><span class="op">:</span><span class="dv">0</span><span class="op">}</span>]</code></pre></div>
- <p>通常这是以某种格式写的,在这里是以JSON写的,而对于一个网站的时候则是HTML,如:</p>
- <div class="sourceCode"><pre class="sourceCode html"><code class="sourceCode html"><span class="kw"><html></span>
- <span class="kw"><head></span>
- <span class="kw"><meta</span><span class="ot"> charset=</span><span class="st">"UTF-8"</span><span class="kw">></span>
- <span class="kw"><title></span>Document<span class="kw"></title></span>
- <span class="kw"></head></span>
- <span class="kw"><body></span>
-
- <span class="kw"></body></span>
- <span class="kw"></html></span> </code></pre></div>
- <p>那么这次GET请求返回的就是:</p>
- <div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">HTTP/1.0</span> 200 OK
- <span class="kw">Date</span>: Mon, 08 Sep 2014 12:04:01 GMT
- <span class="kw">Content-Type</span>: text/html<span class="kw">;</span> <span class="ot">charset=</span>utf-8
- <span class="kw"><html></span>
- <span class="kw"><head></span>
- <span class="kw"><meta</span> charset=<span class="st">"UTF-8"</span><span class="kw">></span>
- <span class="kw"><title></span>Document<span class="kw"><</span>/title<span class="kw">></span>
- <span class="kw"><</span>/<span class="kw">head></span>
- <span class="kw"><body></span>
- [<span class="dt">{"id":1,"temperature":19,"sensors1":31,"sensors2":7.5,"led1":0}</span>]
- <span class="kw"><</span>/<span class="kw">body></span>
- <span class="kw"><</span>/<span class="kw">html></span> </code></pre></div>
- <p>虽然与第一次请求的结果在游览器上看似乎是一样的(ps:可能有微小的差异),然而其本质是不同的。</p>
- <p>推荐及参考书目:</p>
- <ul>
- <li>《Web性能权威指南》</li>
- <li>《图解HTTP》</li>
- <li>《RESTful Web Services Cookbook》</li>
- <li>《RESTful Web APIs》</li>
- </ul>
- <div class="footnotes">
- <hr />
- <ol>
- <li id="fn1"><p>形如http://www.phodal.com<a href="#fnref1">↩</a></p></li>
- <li id="fn2"><p>URL 是 URI 的子集<a href="#fnref2">↩</a></p></li>
- <li id="fn3"><p>curl是利用URL语法在命令行方式下工作的开源文件传输工具。<a href="#fnref3">↩</a></p></li>
- </ol>
- </div>
- </body>
- </html>
|