diff --git a/2.3.md b/2.3.md index 1947e2e7..60bef660 100644 --- a/2.3.md +++ b/2.3.md @@ -3,7 +3,7 @@ ## 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑。流程控制包含分三大类:条件判断,循环控制和无条件跳转。 ### if -`if`也许是各种编程语言中最常见的了,它的语法概括起来就是:`如果满足条件就做某事,否则做另一件事` +`if`也许是各种编程语言中最常见的了,它的语法概括起来就是:如果满足条件就做某事,否则做另一件事。 Go里面`if`条件判断语句中不需要括号,如下代码所示 diff --git a/3.1.md b/3.1.md index 7c526e3c..8998288b 100644 --- a/3.1.md +++ b/3.1.md @@ -1,21 +1,21 @@ # 3.1 Web工作方式 -我们平时浏览网页的时候,打开浏览器,输入网址,按下回车键,然后就出来了内容。在这个看似简单的行为背后,到底隐藏了些什么呢? +我们平时浏览网页的时候,会打开浏览器,输入网址后按下回车键,然后就会显示出你想要浏览的内容。在这个看似简单的用户行为背后,到底隐藏了些什么呢? -上面这个普通的浏览过程,底层其实是这样做的:浏览器是一个客户端,当你输入URL的时候,首先浏览器会去请求DNS服务器,通过DNS获取相应的域名对应的IP,然后通过IP和服务器建立socket连接,发送http请求信息,服务器接收到请求信息之后,处理相应的请求,返回http response信息,客户端接收到http信息之后开始渲染这些http response里面的content信息,断开和服务器的socket链接。 +对于普通的上网过程,系统其实是这样做的:浏览器本身是一个客户端,当你输入URL的时候,首先浏览器会去请求DNS服务器,通过DNS获取相应的域名对应的IP,然后通过IP地址找到IP对应的服务器后,要求建立TCP连接,等浏览器发送完HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包,服务器调用自身服务,返回HTTP Response(响应)包;客户端收到来自服务器的响应后开始渲染这个Response包里的主体(body),等收到全部的内容随后断开与该服务器之间的TCP连接。 ![](images/3.1.web2.png?raw=true) - 一个Web服务器也被称为HTTP服务器,它通过HTTP协议与客户端通信。这个客户端通常指的是Web浏览器(手机端客户端其实内部也是浏览器实现)。 + 一个Web服务器也被称为HTTP服务器,它通过HTTP协议与客户端通信。这个客户端通常指的是Web浏览器(其实手机端客户端内部也是浏览器实现的)。 -Web服务器的工作原理简单的可以归纳为: +Web服务器的工作原理可以简单地归纳为: -- 客户机通过socket建立到服务器的连接 -- 客户端向服务器发送请求,http协议包,请求转化成服务器对应的文档 -- 服务器向客户机发送应答,http协议包,请求的如果包含有动态语言的部分,那么动态语言把相应的数据结果返回给客户端 -- 客户机与服务器断开。客户端解释HTML文档,在客户端屏幕上显示结果 +- 客户机通过TCP/IP协议建立到服务器的TCP连接 +- 客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档 +- 服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端 +- 客户机与服务器断开。由客户端解释HTML文档,在客户端屏幕上渲染图形结果 -一个简单的事务处理事件就是这样实现的,看起来很复杂,做起来其实是挺简单的,需要注意的是客户机与服务器之间的通信是非连接的,也就是当服务器发送了应答后就与客户机断开连接,等待下一次请求。 +一个简单的HTTP事务就是这样实现的,看起来很复杂,原理其实是挺简单的。需要注意的是客户机与服务器之间的通信是非持久连接的,也就是当服务器发送了应答后就与客户机断开连接,等待下一次请求。 ## URL和DNS解析 我们浏览网页都是通过URL访问的,那么URL到底是怎么样的呢? @@ -62,24 +62,22 @@ HTTP协议是Web工作的核心,所以要了解清楚Web的工作方式就需 HTTP是一种让Web服务器与浏览器(客户端)通过Internet发送与接收数据的协议,它建立在TCP协议之上,一般采用TCP的80端口。它是一个请求、响应协议--客户端发出一个请求,服务器响应这个请求。在HTTP中,客户端总是通过建立一个连接与发送一个HTTP请求来发起一个事务。服务器不能主动去与客户端联系,也不能给客户端发出一个回调连接。客户端与服务器端都可以提前中断一个连接。例如,当浏览器下载一个文件时,你可以通过点击“停止”键来中断文件的下载,关闭与服务器的HTTP连接。 -HTTP协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系,对HTTP服务器来说,它并不知道这两个请求来自同一个客户端。 为了解决这个问题, Web程序引入了Cookie机制来维护状态。 +HTTP协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系,对HTTP服务器来说,它并不知道这两个请求是否来自同一个客户端。为了解决这个问题, Web程序引入了Cookie机制来维护连接的可持续状态。 >HTTP协议是建立在TCP协议之上的,因此TCP攻击一样会影响HTTP的通讯,例如比较常见的一些攻击:SYN Flood是当前最流行的DoS(拒绝服务攻击)与DdoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。 -### HTTP请求信息(浏览器信息) +### HTTP请求包(浏览器信息) -我们先来看看Request消息的结构, Request 消息分为3部分,第一部分叫Request line, 第二部分叫Request header,第三部分是body。header和body之间有个空行,详细的如下所示 +我们先来看看Request包的结构, Request包分为3部分,第一部分叫Request line(请求行), 第二部分叫Request header(请求头),第三部分是body(主体)。header和body之间有个空行,请求包的例子所示: - - 请求行:GET/POST(流的组织(请求)方式) URL(地址+目录) 版本号 - - 请求头: - - Host:客户端IP和端口 - User-Agent:浏览器信息 - Accept:客户端能接收的数据类型 - Accept-encoding:是否支持压缩的流 - Accept-charset:客户端字符编码集 - - 空行:分割请求头和消息体 - - 消息体:请求的参数 + GET /domains/example/ HTTP/1.1 //请求行: 请求方法 请求URI HTTP协议/协议版本 + Host:www.iana.org //服务端的主机名 + User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4 //浏览器信息 + Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 //客户端能接收的mine + Accept-Encoding:gzip,deflate,sdch //是否支持流压缩 + Accept-Charset:UTF-8,*;q=0.5 //客户端字符编码集 + //空行,用于分割请求头和消息体 + //消息体,请求资源参数,例如POST传递的参数 我们通过fiddler抓包可以看到如下请求信息 @@ -87,36 +85,36 @@ HTTP协议是无状态的,同一个客户端的这次请求和上次请求是 ![](images/3.1.httpPOST.png?raw=true) -我们可以看到GET请求消息体为空,POST请求带有消息体。 +**我们可以看到GET请求消息体为空,POST请求带有消息体**。 -Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET,POST,PUT,DELETE. 一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,改,增,删4个操作。 我们最常见的就是GET和POST了。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息. +HTTP协议定义了很多与服务器交互的请求方法,最基本的有4种,分别是GET,POST,PUT,DELETE. 一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,改,增,删4个操作。 我们最常见的就是GET和POST了。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息. 我们看看GET和POST的区别 1. GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中. 2. GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制. 3. GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码。 -### HTTP响应信息(服务器信息) -我们再来看看HTTP的response信息,他的结构如下: +### HTTP响应包(服务器信息) +我们再来看看HTTP的response包,他的结构如下: - - 状态行:HTTP版本 服务器状态(比如:404找不到...) 描述信息 - - 响应头 + HTTP/1.1 200 OK //状态行 + Server: nginx/1.0.8 //服务器使用的WEB软件名及版本 + Date:Date: Tue, 30 Oct 2012 04:14:25 GMT //发送时间 + Content-Type: text/html //服务器发送信息的类型 + Transfer-Encoding: chunked //表示发送HTTP包是分段发的 + Connection: keep-alive //保持连接状态 + Content-Length: 90 //主体内容长度 + //空行 用来分割消息头和主体 + 网页优化方面有一项是减少http请求次数,就是把尽量多的css和js合并在一起,尽量做到少的http请求。 +>网页优化方面有一项措施是减少HTTP请求次数,就是把尽量多的css和js资源合并在一起,目的是尽量减少网页请求静态资源的次数,提高网页加载速度,同时减缓服务器的压力。 ## links * [目录]() diff --git a/3.2.md b/3.2.md index 0ea4397e..9f0f6ea3 100644 --- a/3.2.md +++ b/3.2.md @@ -50,13 +50,13 @@ 我们看到上面的代码,要编写一个web服务器很简单,只要调用http包的两个函数就可以了。 ->- 如果你以前是PHP程序员,那你也许就会问,我们的nginx、apache服务器不需要吗?Go就是不需要这些,因为他直接就监听tcp端口了,做了nginx做的事情,然后sayhelloName这个其实就是我们写的逻辑函数了,也就是php里面的执行逻辑类似。 +>如果你以前是PHP程序员,那你也许就会问,我们的nginx、apache服务器不需要吗?Go就是不需要这些,因为他直接就监听tcp端口了,做了nginx做的事情,然后sayhelloName这个其实就是我们写的逻辑函数了,也就是php里面的控制层(controller)函数类似。 ->- 如果你以前是python程序员,那么你一定听说过tornado,这个代码和他是不是很像,对,没错,go就是拥有类似python这样动态语言的特性,写web应用很方便。 +>如果你以前是python程序员,那么你一定听说过tornado,这个代码和他是不是很像,对,没错,go就是拥有类似python这样动态语言的特性,写web应用很方便。 ->- 如果你以前是ruby程序员,那么和ROR的/script/server启动有点类似。 +>如果你以前是ruby程序员,那么和ROR的/script/server启动有点类似。 -我们看到Go通过简单的几行代码就已经运行起来一个web服务了,而且这个Web服务内部已经支持了高并发的特性,我将会在接下来的两个小节里面详细的讲解一下go是如何实现Web高并发的。 +我们看到Go通过简单的几行代码就已经运行起来一个web服务了,而且这个Web服务内部有支持高并发的特性,我将会在接下来的两个小节里面详细的讲解一下go是如何实现Web高并发的。 ## links * [目录]() diff --git a/3.3.md b/3.3.md index 197b7365..1cb06a15 100644 --- a/3.3.md +++ b/3.3.md @@ -1,9 +1,9 @@ # 3.3 Go如何使得Web工作 -前面小节介绍了如何通过Go搭建一个Web服务,我们可以看到简单的应用了一个net/http包就方便的搭建起来了。那么他底层到底是怎么做的呢?万变不离其宗,Go也离不开我们第一小节介绍的Web工作方式。 +前面小节介绍了如何通过Go搭建一个Web服务,我们可以看到简单应用一个net/http包就方便的搭建起来了。那么Go在底层到底是怎么做的呢?万变不离其宗,Go的Web服务工作也离不开我们第一小节介绍的Web工作方式。 -## 对应web工作方式的几个概念 +## web工作方式的几个概念 -以下均是服务器端的相应概念 +以下均是服务器端的几个概念 Request:用户请求的信息,用来解析用户的请求信息,包括post、get、cookie、url等信息 @@ -15,15 +15,15 @@ Handler:处理请求和生成返回信息的处理逻辑 ## 分析http包运行机制 -如下图所示,是Go实现Web工作模式的流程图 +如下图所示,是Go实现Web服务的工作模式的流程图 ![](images/3.3.http.png?raw=true) -(1) 创建listen socket, 在指定的端口监听, 等待客户端请求的到来。 +1. 创建Listen Socket, 监听指定的端口, 等待客户端请求到来。 -(2) listen socket接受客户端的请求, 得到client socket, 接下来通过client socket与客户端通信。 +2. Listen Socket接受客户端的请求, 得到Client Socket, 接下来通过Client Socket与客户端通信。 -(3) 处理客户端的请求, 首先从client socket读取http请求的协议头, 如果是post协议, 还可能要读取客户端上传的数据, 然后扔给相应的handler处理请求, handler处理完毕准备好客户端需要的数据, 通过client socket写给客户端。 +3. 处理客户端的请求, 首先从Client Socket读取HTTP请求的协议头, 如果是POST方法, 还可能要读取客户端提交的数据, 然后交给相应的handler处理请求, handler处理完毕准备好客户端需要的数据, 通过Client Socket写给客户端。 这整个的过程里面我们只要了解清楚下面三个问题,也就知道Go是如何让Web运行起来了 @@ -31,17 +31,17 @@ Handler:处理请求和生成返回信息的处理逻辑 - 如何接收客户端请求? - 如何分配handler? -前面小节的代码里面我们可以看到,Go是通过一个函数来操作这个事情的`ListenAndServe`来监听起来的,这个底层其实这样处理的:初始化一个server对象,然后调用了`net.Listen("tcp", addr)`,也就是底层起的是TCP协议,然后监控了我们设置的端口。 +前面小节的代码里面我们可以看到,Go是通过一个函数来操作这个事情的`ListenAndServe`来监听起来的,这个底层其实这样处理的:初始化一个server对象,然后调用了`net.Listen("tcp", addr)`,也就是底层用TCP协议搭建了一个服务,然后监控我们设置的端口。 -监控之后如何接收客户端的请求呢?上面的监控端口之后,就调用了`srv.Serve(net.Listener)`函数,这个函数就是处理接收客户端的请求信息。这个函数里面起了一个`for{}`,首先通过Listener接收请求,其次起一个Conn,最后单独开了一个goroutine,把这个请求的数据当做参数扔给这个conn去服务:`go c.serve()`。这个就是高并发体现了,用户来的请求都是goroutine去服务,相互不影响。 +监控之后如何接收客户端的请求呢?上面代码执行监控端口之后,调用了`srv.Sere(net.Listener)`函数,这个函数就是处理接收客户端的请求信息。这个函数里面起了一个`for{}`,首先通过Listener接收请求,其次创建一个Conn,最后单独开了一个goroutine,把这个请求的数据当做参数扔给这个conn去服务:`go c.serve()`。这个就是高并发体现了,用户的每一次请求都是在一个新的goroutine去服务,相互不影响。 -那么如何具体分配到相应的函数来处理请求呢?conn首先会解析request:`c.readRequest()`,然后获取相应的handler:`handler := c.server.Handler`,也就是我们刚才在调用函数`ListenAndServe`时候的第二个参数,我们前面例子传递的是nil,也就是为空,那么默认获取`handler = DefaultServeMux`,那么这个变量用来做什么的呢?对,这个变量就是一个路由器,它用来把url匹配到其相应的handle函数,那么这个我们有设置过吗?有,我们调用的代码里面第一句不是调用了`http.HandleFunc("/", sayhelloName)`嘛。这个就是注册了相应的路由,url为"/"的请求到函数sayhelloName,DefaultServeMux会调用ServeHTTP方法,这个方法内部其实就是调用sayhelloName本身,最后通过写入response的信息反馈到客户端。 +那么如何具体分配到相应的函数来处理请求呢?conn首先会解析request:`c.readRequest()`,然后获取相应的handler:`handler := c.server.Handler`,也就是我们刚才在调用函数`ListenAndServe`时候的第二个参数,我们前面例子传递的是nil,也就是为空,那么默认获取`handler = DefaultServeMux`,那么这个变量用来做什么的呢?对,这个变量就是一个路由器,它用来匹配url跳转到其相应的handle函数,那么这个我们有设置过吗?有,我们调用的代码里面第一句不是调用了`http.HandleFunc("/", sayhelloName)`嘛。这个作用就是注册了请求`/`的路由规则,当请求uri为"/",路由就会转到函数sayhelloName,DefaultServeMux会调用ServeHTTP方法,这个方法内部其实就是调用sayhelloName本身,最后通过写入response的信息反馈到客户端。 详细的整个流程如下图所示: ![](images/3.3.illustrator.png?raw=true) -至此我们的三个问题已经全部得到了解答,你现在对于Go如何让Web跑起来的是否已经大概清楚了呢? +至此我们的三个问题已经全部得到了解答,你现在对于Go如何让Web跑起来的是否已经基本了解呢? ## links