|
1 | | -#3.3 Go如何使得Web工作 |
2 | | -前面小节介绍了如何通过Go搭建一个Web服务,我们可以看到简单的应用了一个net/http包就方便的搭建起来了。那么他底层到底是怎么做的呢?万变不离其宗,Go也离不开我们第一小节介绍的Web工作方式。 |
3 | | - |
4 | | -##对应web工作方式的几个概念 |
5 | | - |
6 | | -以下均是服务器端的相应概念 |
7 | | - |
8 | | -Request:用户请求的信息,用来解析用户的请求信息,包括post、get、cookie、url等信息 |
9 | | - |
10 | | -Response:服务器需要反馈给客户端的信息 |
11 | | - |
12 | | -Conn:用户的每次请求链接 |
13 | | - |
14 | | -Handler:处理请求和生成返回信息的处理逻辑 |
15 | | - |
16 | | -##分析http包运行机制 |
17 | | - |
18 | | -如下图所示,是Go实现Web工作模式的流程图 |
19 | | - |
20 | | - |
21 | | - |
22 | | -(1) 创建listen socket, 在指定的端口监听, 等待客户端请求的到来。 |
23 | | - |
24 | | -(2) listen socket接受客户端的请求, 得到client socket, 接下来通过client socket与客户端通信。 |
25 | | - |
26 | | -(3) 处理客户端的请求, 首先从client socket读取http请求的协议头, 如果是post协议, 还可能要读取客户端上传的数据, 然后扔给相应的handler处理请求, handler处理完毕准备好客户端需要的数据, 通过client socket写给客户端。 |
27 | | - |
28 | | -这整个的过程里面我们只要了解清楚下面三个问题,也就知道Go是如何让Web运行起来了 |
29 | | - |
30 | | -- 如何监听端口? |
31 | | -- 如何接收客户端请求? |
32 | | -- 如何分配handler? |
33 | | - |
34 | | -前面小节的代码里面我们可以看到,Go是通过一个函数来操作这个事情的`ListenAndServe`来监听起来的,这个底层其实这样处理的:初始化一个server对象,然后调用了`net.Listen("tcp", addr)`,也就是底层起的是TCP协议,然后监控了我们设置的端口。 |
35 | | - |
36 | | -监控之后如何接收客户端的请求呢?上面的监控端口之后,就调用了`srv.Serve(net.Listener)`函数,这个函数就是处理接收客户端的请求信息。这个函数里面起了一个`for{}`,首先通过Listener接收请求,其次起一个Conn,最后单独开了一个goroutine,把这个请求的数据当做参数扔给这个conn去服务:`go c.serve()`。这个就是高并发体现了,用户来的请求都是goroutine去服务,相互不影响。 |
37 | | - |
| 1 | +#3.3 Go如何使得Web工作 |
| 2 | +前面小节介绍了如何通过Go搭建一个Web服务,我们可以看到简单的应用了一个net/http包就方便的搭建起来了。那么他底层到底是怎么做的呢?万变不离其宗,Go也离不开我们第一小节介绍的Web工作方式。 |
| 3 | + |
| 4 | +##对应web工作方式的几个概念 |
| 5 | + |
| 6 | +以下均是服务器端的相应概念 |
| 7 | + |
| 8 | +Request:用户请求的信息,用来解析用户的请求信息,包括post、get、cookie、url等信息 |
| 9 | + |
| 10 | +Response:服务器需要反馈给客户端的信息 |
| 11 | + |
| 12 | +Conn:用户的每次请求链接 |
| 13 | + |
| 14 | +Handler:处理请求和生成返回信息的处理逻辑 |
| 15 | + |
| 16 | +##分析http包运行机制 |
| 17 | + |
| 18 | +如下图所示,是Go实现Web工作模式的流程图 |
| 19 | + |
| 20 | + |
| 21 | + |
| 22 | +(1) 创建listen socket, 在指定的端口监听, 等待客户端请求的到来。 |
| 23 | + |
| 24 | +(2) listen socket接受客户端的请求, 得到client socket, 接下来通过client socket与客户端通信。 |
| 25 | + |
| 26 | +(3) 处理客户端的请求, 首先从client socket读取http请求的协议头, 如果是post协议, 还可能要读取客户端上传的数据, 然后扔给相应的handler处理请求, handler处理完毕准备好客户端需要的数据, 通过client socket写给客户端。 |
| 27 | + |
| 28 | +这整个的过程里面我们只要了解清楚下面三个问题,也就知道Go是如何让Web运行起来了 |
| 29 | + |
| 30 | +- 如何监听端口? |
| 31 | +- 如何接收客户端请求? |
| 32 | +- 如何分配handler? |
| 33 | + |
| 34 | +前面小节的代码里面我们可以看到,Go是通过一个函数来操作这个事情的`ListenAndServe`来监听起来的,这个底层其实这样处理的:初始化一个server对象,然后调用了`net.Listen("tcp", addr)`,也就是底层起的是TCP协议,然后监控了我们设置的端口。 |
| 35 | + |
| 36 | +监控之后如何接收客户端的请求呢?上面的监控端口之后,就调用了`srv.Serve(net.Listener)`函数,这个函数就是处理接收客户端的请求信息。这个函数里面起了一个`for{}`,首先通过Listener接收请求,其次起一个Conn,最后单独开了一个goroutine,把这个请求的数据当做参数扔给这个conn去服务:`go c.serve()`。这个就是高并发体现了,用户来的请求都是goroutine去服务,相互不影响。 |
| 37 | + |
38 | 38 | 那么如何具体分配到相应的函数来处理请求呢?conn首先会解析request:`c.readRequest()`,然后获取相应的handler:`handler := c.server.Handler`,也就是我们刚才在调用函数`ListenAndServe`时候的第二个参数,我们前面例子传递的是nil,也就是为空,那么默认获取`handler = DefaultServeMux`,那么这个变量用来做什么的呢?对,这个变量就是一个路由器,它用来把url匹配到其相应的handle函数,那么这个我们有设置过吗?有,我们调用的代码里面第一句不是调用了`http.HandleFunc("/", sayhelloName)`嘛。这个就是注册了相应的路由,url为"/"的请求到函数sayhelloName,DefaultServeMux会调用ServeHTTP方法,这个方法内部其实就是调用sayhelloName本身,最后通过写入response的信息反馈到客户端。 |
39 | 39 |
|
40 | 40 | 详细的整个流程如下图所示: |
41 | 41 |
|
42 | | - |
43 | | - |
44 | | -至此我们的三个问题已经全部得到了解答,你现在对于Go如何让Web跑起来的是否已经大概清楚了呢? |
45 | | - |
46 | | - |
47 | | -## links |
48 | | - * [目录](<preface.md>) |
49 | | - * 上一节: [GO搭建一个简单的web服务](<3.2.md>) |
50 | | - * 下一节: [Go的http包详解](<3.4.md>) |
51 | | - |
52 | | -## LastModified |
53 | | - * $Id$ |
| 42 | + |
| 43 | + |
| 44 | +至此我们的三个问题已经全部得到了解答,你现在对于Go如何让Web跑起来的是否已经大概清楚了呢? |
| 45 | + |
| 46 | + |
| 47 | +## links |
| 48 | + * [目录](<preface.md>) |
| 49 | + * 上一节: [GO搭建一个简单的web服务](<3.2.md>) |
| 50 | + * 下一节: [Go的http包详解](<3.4.md>) |
| 51 | + |
| 52 | +## LastModified |
| 53 | + * $Id$ |
0 commit comments