Linux网络原理与编程(2)——第十二节 应用层协议(以HTTP为例)

目录

协议

HTTP协议

认识URL

HTTP协议的特征

HTTP的构成及报文格式

报文格式

请求方法

常见的Header

状态码


我们从本节开始,就来正式地详细介绍网络各个层次的内容。

我们先从最顶端的应用层协议说起。

在说应用层协议之前,我们来思考一下什么叫协议?

协议

协议是一种 "约定". socket api的接口, 在读写数据时, 都是按 "字符串" 的方式来发送接收的。更准确点来说,收发是按照比特位的形式进行的。

对于协议的理解,抓住本质:它就是一种协议。有了这种协议,大家都遵守的协议,那么在不同的主机收发数据的时候,就有了读取的标准,这样在序列化和反序列化、读取大小等都有了参照的标准。

那么作为IOS模型的最顶端——应用层协议,都有哪些特点呢?我们现在就来详细地讨论一下。

本节,我们的应用层协议主要以Http为例,主要学习http的报文格式、特性等。

HTTP协议

首先需要明确的是,对于包含http协议在内的应用层协议,不属于内核,都是由程序员自己来定的。也就是说,http的报文格式到底是怎么样的,是程序员自己决定的。

认识URL

比如我现在有这样一个所谓的链接:https://translate.google.cn/?sl=auto&tl=zh-CN&text=%20contiguous%20characters&op=translate

 

这样的链接,我们称之为URL

这样的一个URL,我们可以分成这样几块:

前面的https,为协议名;即我所使用的协议是https协议。

而后面的translate.google.cn或者是sports.qq.com,它们都是服务器地址;

再往后不同的链接就不一样了。大多数都是带层次的文件名、字符串查询符号、文段标识符等。

当然,在一个URL里,通常也会包含登录信息和端口号。但是我们这个通常不写。前者是因为浏览器知道你是谁,而后者是因为协议和端口一般是强绑定。比如https绑定的端口号就是443。

HTTP协议的特征

三个特征:

1、无状态;

2、无连接;

3、简单快速。

重点来解释前两个。

先来解释第一个:HTTP是建立在TCP协议的基础之上,那这和底层基于TCP协议是不是矛盾呢?其实之前就已经说过,HTTP作为上层,是不关心底层(下面一层)具体是怎么实现的细节的。

换句话来说:你TCP链不链接和我HTTP没有丝毫的关系。

所以说,HTTP直接把数据和报文的request发给底层的TCP就可以了,不需要考虑和对方链接的问题,至于要通过链接解决可靠性等问题,那是你底层TCP的事情,与我HTTP无关。所以说http是可以不用保证可靠性的(简而言之就是,因为http是基于tcp的,而tcp保证了可靠,所以http就不用保证啦)。

无状态:http本身是无状态的,并不会记录任何用户信息,只会发出request,然后得到response。记录你访问信息的是cookie + session

短链接进行文本传输(文本:html,img,css,js…)http/1.0

 现在的http/1.1:也支持长连接

再来说说简单快速吧:简单是说其就是基于简单的链接,一来一回响应一个request和response就完了。 快速高效就也体现在其底层用的是tcp,并且可以传送各种文本资源。

HTTP的构成及报文格式

报文格式

http的报文分为两大类:

request报文和response报文

request报文和response报文的格式如下:

 (1)在http报文的第一行是请求行,包含请求方法、url和 http的版本(version)(2)

(2)然后在下面的若干行,是一些key/value值;主要是一些属性。比如用户名、是否为长连接等。

(3)然后是空行;

(4)最后是请求报文的正文部分。

(还是先去接受,因为我这些知识本身就是一个闭环,只有把这些知识全都介绍完之后,才能够明白来龙去脉)

对于Response报文:

 (1)如上图,与Requst报文类似,response报文分为四块。分别是相应行、响应报头、空行和响应正文。

在第一行的响应行里,首先是response的版本,然后是退出状态码,接着是对退出状态码的描述。

(2)接下来的若干行依旧是响应报头的key/value值,存储的是一些属性。值得注意的是,这里面包含一行为Content-Length,它表示的是对应响应正文的大小。

(3)再接下来是一行空行。

(4)然后是响应正文部分。

整个过程如下图所示:

当服务器收到一个request后,需要返回一个response

 一次响应、一次请求结束之后,如果是短连接,那么短连接结束,服务端的文件描述符直接close掉,连接断开。

对于报文的内容,我们一会还会详细叙述,现在,我们来说一说该报文的可行性(即实际可操作性):

问:即我作为读的一方,我怎么知道我已经将HTTP的请求包括数据全部读完了呢?

答:首先,由于其是 以行 为单位来去写的,所以,就要以行为单位来去读。

所以当读到\n的时候,我就知道我这一行读完了

当我读到空行的时候,我就知道我已经把报头读完了。

下面的正文该读多少,取决于在请求报头当中的key值后面的value.(即其中一个key:value所表明的就是请求正文里有多少个字节,具体来说是Content-length:xxx,所以读取的时候,只要根据这个数值来就可以了)(注意,由于许多个http请求报文可能是连在一块的,所以是需要这个读取数值的,不是一股脑的将所有的数据全部读完)

注意:由于HTTP上层已经没有协议了,所以其不需要解决交付的问题,只需要解决分离的问题就可以了。

好的,我们现在来介绍一些细节。

请求方法

我们上网一般就干两件事:把人家的数据拿下来,或者将数据上传到网站上

那么在请求报文中,体现出来的就是POST方法和GET方法。POST就表示我要将我的报文的数据传递到某个网站上;GET相反,表示我要从某个网站上获取信息。

当然,我们的请求方法不止POST和GET两种。具体见下图:

 

常见的Header

这里的Header的意思就是报头上的key : value的key值。

它通常会有如下这些(这些通常也是比较常见、比较基本的):

1、Content-Type: 数据类型(text/html等)

2、Content-Length: Body的长度

3、Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;

4、User-Agent: 声明用户的操作系统和浏览器版本信息; (可以通过判断是否携带该信息来判断是否为机器爬虫)

5、referer: 当前页面是从哪个页面跳转过来的;

6、location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;

7、Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能

状态码

我们通常在网页中的404,它其实就是状态码。状态码通常也是约定俗成、认为规定的。通常,状态码和状态码的含义有如下的对应关系:

 解释一些4xx和5xx:

4xx表示资源找不到,但这个是客户端的锅,客户端找的资源压根不合理

而5xx资源找不到的原因是因为服务器崩了,这个锅是服务器的。

注意一下二者的区别。

通常的,像200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)

我们现在来尝试抓一个http包:

我们用Fiddler来进行抓包:

如上图,是我在访问baidu.com的时候,抓的https的报文。

依照着改图,我们再来补充一些知识。

首先注意里面有一个 keep-alive,表示长链接(close表示短链接)。

可不是说http是无连接的吗?注意,再次强调,我们链接的打开与关闭,是由我们自己控制,http的无连接,是指http发送一个request,然后再拿回来一个resonpse就完了。而底层的tcp链接要不要关闭是取决于http协议的,http复用了这个链接,选择长连接或者短链接。

注意到上面还有一行,是用来发送自己的平台信息和浏览器等相关的信息(这就解释了为什么我们平时在安装软件的时候,浏览器能够自动识别我们的电脑相关的信息(比如是x64平台,win版本))

还有一行cookie。

我们知道,http是无状态的,所以需要我们登录才能访问的有很多场景,可是,我们在实际中发现浏览器好像能够有一定的记忆,记得我的信息,可是http本身是无状态的,这又怎么解释呢?

HTTP本身是无状态的不错,但是HTTP是给用户用的,如果无状态,就会给用户造成很差的用户体验。那怎么办呢?

先说cookie是什么。

本质上,cookie就是一个文件。

保存在本地的文件(当然也有内存级的cookie)。那么每一次,在request当中,有一个cookie作为value值发出去了,在response中,有一个set-cookie。这个cookie是客户端向服务器发,而set-cookie指服务器向客户端写入的内容(实际上是一种文件)

(如下图) 

那么cookie的作用,就是我只要输入了一次,后续我就不用再输入啦,这样会给予用户比较良好的用户体验。

举一个简单的例子:

当我们的http请求去访问服务器的时候,服务器是能够拿到我们的账号和密码的。而服务器是要给我们的客户端一个response,那么在这个response当中,服务器就会以set-cookie的方式,将我们的账号和密码返回给客户端,客户端就会以cookie的形式保存到浏览器中。而cookie的本质是浏览器的一种文件。

从此往后,在一段特定的时间内,客户端在下一次http请求的时候,会在request里自动将cookie里携带的信息以key:value的形式发送给服务器。这样,服务器就够能拿到我们的账号密码,就不需要用户自动输入了。

(当然,如果我们清理掉我们的cookie,那就要重新输入了)

注意:这里的cookie分为内存级的和硬盘级的。

那如果有黑客来入侵我的主机,那他岂不是能够拿到我的cookie干坏事了吗?

那怎么解决呢?

这就演变出了session

这是怎么一回事呢?

当第一次输入了账号密码的时候,在服务器端会通过这个账号密码,生成一个全网唯一的一个sid,然后将你的账号密码存储在server服务器端的一个session文件当中,然后,给用户返回的是一个sid,这个sid将会以set-cookie : sid = XXX的形式返回,然后下一次客户端再来访问的时候,直接拿着这个sid来访问,服务器端通过这个sid来去找到对应的session文件当中对应的账户是否处于登录状态,如果是,那就算是登录成功了。

这个时候,即使黑客拿,也只能拿到我的sid,却什么也做不了。最多代替我进行访问,可是我的账号密码信息并未泄露。

好啦,本节的内容我们就到这里啦,在下一节,我们将会为大家来解释http和https之间的关系。

  • 3
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 3
    评论
目录 《linux网络编程(第2版)》 第1篇 linux网络开发基础 第1章 linux操作系统概述 2 1.1 linux发展历史 2 1.1.1 linux的诞生和发展 2 1.1.2 linux名称的由来 3 1.2 linux的发展要素 3 1.2.1 unix操作系统 3 1.2.2 minix操作系统 4 1.2.3 posix 标准 4 1.3 linux与unix的异同 5 1.4 操作系统类型选择和内核版本的选择 5 1.4.1 常见的不同公司发行的linux异同 5 1.4.2 内核版本的选择 6 1.5 linux的系统架构 7 1.5.1 linux内核的主要模块 7 1.5.2 linux的文件结构 8 1.6 gnu通用公共许可证 9 1.6.1 gpl许可证的历史 9 1.6.2 gpl的自由理念 10 1.6.3 gpl的基本条款 11 1.6.4 关于gpl许可证的争议 12 1.7 linux软件开发的可借鉴之处 12 1.8 小结 13 第2章 linux编程环境 14 2.1 linux环境下的编辑器 14 2.1.1 vim使用简介 14 2.1.2 使用vim建立文件 15 2.1.3 使用vim编辑文本 16 2.1.4 vim的格式设置 18 2.1.5 vim配置文件.vimrc 18 2.1.6 使用其他编辑器 19 2.2 linux下的gcc编译器工具集 19 2.2.1 gcc简介 19 2.2.2 编译程序的基本知识 21 2.2.3 单个文件编译成执行文件 21 2.2.4 编译生成目标文件 22 2.2.5 多文件编译 22 2.2.6 预处理 24 2.2.7 编译成汇编语言 24 2.2.8 生成和使用静态链接库 25 2.2.9 生成动态链接库 26 2.2.10 动态加载库 29 2.2.11 gcc常用选项 31 2.2.12 编译环境的搭建 33 2.3 makefile文件简介 33 2.3.1 一个多文件的工程例子 33 2.3.2 多文件工程的编译 35 2.3.3 makefile的规则 37 2.3.4 makefile中使用变量 39 2.3.5 搜索路径 42 2.3.6 自动推导规则 43 2.3.7 递归make 44 2.3.8 makefile中的函数 46 2.4 用gdb调试程序 47 2.4.1 编译可调试程序 48 2.4.2 使用gdb调试程序 49 2.4.3 gdb常用命令 52 2.4.4 其他的gdb 59 2.5 小结 60 第3章 文件系统简介 61 3.1 linux下的文件系统 61 3.1.1 linux下文件的内涵 61 3.1.2 文件系统的创建 62 3.1.3 挂接文件系统 65 3.1.4 索引点inode 65 3.1.5 普通文件 66 3.1.6 设备文件 66 3.1.7 虚拟文件系统vfs 68 3.2 文件的通用操作方法 72 3.2.1 文件描述符 72 3.2.2 打开创建文件open()函数、create()函数 73 3.2.3 关闭文件close()函数 76 3.2.4 读取文件read()函数 77 3.2.5 写文件write()函数 79 3.2.6 文件偏移lseek()函数 80 3.2.7 获得文件状态fstat()函数 83 3.2.8 文件空间映射mmap()函数 85 3.2.9 文件属性fcntl()函数 88 3.2.10 文件输入输出控制ioctl()函数 92 3.3 socket文件类型 93 3.4 小结 93 第4章 程序、进程和线程 94 4.1 程序、进程和线程的概念 94 4.1.1 程序和进程的差别 94 4.1.2 linux环境下的进程 95 4.1.3 进程和线程 96 4.2 进程产生的方式 96 4.2.1 进程号 96 4.2.2 进程复制fork()函数 97 4.2.3 system()函数方式 98 4.2.4 进程执行exec()函数系列 99 4.2.5 所有用户态进程的产生进程init 100 4.3 进程间通信和同步 101 4.3.1 半双工管道 101 4.3.2 命名管道 107 4.3.3 消息队列 108 4.3.4 消息队列的一个例子 114 4.3.5 信号量 116 4.3.6 共享内存 121 4.3.7 信号 124 4.4 linux下的线程 127 4.4.1 多线程编程实例 127 4.4.2 linux下线程创建函数pthread_create() 129 4.4.3 线程的结束函数pthread_join()和函数pthread_exit() 129 4.4.4 线程的属性 130 4.4.5 线程间的互斥 132 4.4.6 线程中使用信号量 133 4.5 小结 136 第2篇 linux用户层网络编程 第5章 tcp/ip协议族简介 138 5.1 osi网络分层介绍 138 5.1.1 osi网络分层结构 138 5.1.2 osi的7层网络结构 139 5.1.3 osi参考模型中的数据传输 140 5.2 tcp/ip协议栈 141 5.2.1 tcp/ip协议栈参考模型 141 5.2.2 主机到网络协议 143 5.2.3 ip协议 144 5.2.4 网际控制报文协议(icmp) 146 5.2.5 传输控制协议(tcp) 150 5.2.6 用户数据报文协议(udp) 154 5.2.7 地址解析协议(arp) 156 5.3 ip地址分类与tcp/udp端口 158 5.3.1 因特网中ip地址的分类 159 5.3.2 子网掩码(subnet mask address) 161 5.3.3 ip地址的配置 162 5.3.4 端口 163 5.4 主机字序和网络序 163 5.4.1 字序的含义 163 5.4.2 网络序的转换 164 5.5 小结 166 第6章 应用层网络服务程序简介 167 6.1 http协议和服务 167 6.1.1 http协议概述 167 6.1.2 http协议的基本过程 168 6.2 ftp协议和服务 170 6.2.1 ftp协议概述 170 6.2.2 ftp协议的工作模式 172 6.2.3 ftp协议的传输方式 172 6.2.4 一个简单的ftp过程 173 6.2.5 常用的ftp工具 173 6.3 telnet协议和服务 173 6.3.1 远程登录的基本概念 174 6.3.2 使用telnet协议进行远程登录的工作过程 174 6.3.3 telnet协议 174 6.4 nfs协议和服务 175 6.4.1 安装nfs服务器和客户端 175 6.4.2 服务器端的设定 176 6.4.3 客户端的操作 176 6.4.4 showmount命令 177 6.5 自定义网络服务 177 6.5.1 xinetd/inetd 177 6.5.2 xinetd服务配置 178 6.5.3 自定义网络服务 179 6.6 小结 180 第7章 tcp网络编程基础 181 7.1 套接字编程基础知识 181 7.1.1 套接字地址结构 181 7.1.2 用户层和内核层交互过程 183 7.2 tcp网络编程流程 184 7.2.1 tcp网络编程架构 184 7.2.2 创建网络插口函数socket() 186 7.2.3 绑定一个地址端口对函数bind() 189 7.2.4 监听本地端口listen 192 7.2.5 接受一个网络请求函数accept() 194 7.2.6 连接目标网络服务器函数connect() 199 7.2.7 写入数据函数write() 200 7.2.8 读取数据函数read() 201 7.2.9 关闭套接字函数 202 7.3 服务器/客户端的简单例子 202 7.3.1 例子功能描述 202 7.3.2 服务器网络程序 202 7.3.3 服务器读取和显示字符串 205 7.3.4 客户端的网络程序 205 7.3.5 客户端读取和显示字符串 206 7.3.6 编译运行程序 206 7.4 截取信号的例子 207 7.4.1 信号处理 207 7.4.2 信号sigpipe 207 7.4.3 信号sigint 208 7.5 小结 208 第8章 服务器和客户端信息的获取 209 8.1 字序 209 8.1.1 大端字序和小端字序 209 8.1.2 字序转换函数 211 8.1.3 一个字序转换的例子 213 8.2 字符串ip地址和二进制ip地址的转换 216 8.2.1 inet_xxx()函数 216 8.2.2 inet_pton()和inet_ntop()函数 218 8.2.3 使用8.2.1地址转换函数的例子 219 8.2.4 使用函数inet_pton()和函数inet_ntop()的例子 221 8.3 套接字描述符判定函数issockettype() 222 8.3.1 进行文件描述符判定的函数issockettype() 222 8.3.2 main()函数 223 8.4 ip地址与域名之间的相互转换 223 8.4.1 dns原理 223 8.4.2 获取主机信息的函数 224 8.4.3 使用主机名获取主机信息的例子 227 8.4.4 函数gethostbyname()不可重入的例子 229 8.5 协议名称处理函数 230 8.5.1 xxxprotoxxx()函数 231 8.5.2 使用协议族函数的例子 232 8.6 小结 235 第9章 数据的io和复用 236 9.1 io函数 236 9.1.1 使用recv()函数接收数据 236 9.1.2 使用send()函数发送数据 238 9.1.3 使用readv()函数接收数据 239 9.1.4 使用writev()函数发送数据 239 9.1.5 使用recvmsg()函数接收数据 241 9.1.6 使用sendmsg()函数发送数据 243 9.1.7 io函数的比较 245 9.2 使用io函数的例子 245 9.2.1 客户端处理框架的例子 245 9.2.2 服务器端程序框架 247 9.2.3 使用recv()和send()函数 248 9.2.4 使用readv()和write()函数 250 9.2.5 使用recvmsg()和sendmsg()函数 252 9.3 io模型 255 9.3.1 阻塞io模型 255 9.3.2 非阻塞io模型 255 9.3.3 io复用 256 9.3.4 信号驱动io模型 256 9.3.5 异步io模型 257 9.4 select()函数和pselect()函数 258 9.4.1 select()函数 258 9.4.2 pselect()函数 260 9.5 poll()函数和ppoll()函数 261 9.5.1 poll()函数 261 9.5.2 ppoll()函数 262 9.6 非阻塞编程 263 9.6.1 非阻塞方式程序设计介绍 263 9.6.2 非阻塞程序设计的例子 263 9.7 小结 264 第10章 基于udp协议的接收和发送 265 10.1 udp编程框架 265 10.1.1 udp编程框图 265 10.1.2 udp服务器编程框架 267 10.1.3 udp客户端编程框架 267 10.2 udp协议程序设计的常用函数 267 10.2.1 建立套接字socket()和绑定套接字bind() 268 10.2.2 接收数据recvfrom()/recv() 268 10.2.3 发送数据sendto()/send() 273 10.3 udp接收和发送数据的例子 277 10.3.1 udp服务器端 277 10.3.2 udp服务器端数据处理 278 10.3.3 udp客户端 279 10.3.4 udp客户端数据处理 279 10.3.5 测试udp程序 280 10.4 udp协议程序设计中的几个问题 280 10.4.1 udp报文丢失数据 280 10.4.2 udp数据发送中的乱序 282 10.4.3 udp协议中的connect()函数 284 10.4.4 udp缺乏流量控制 285 10.4.5 udp协议中的外出网络接口 287 10.4.6 udp协议中的数据报文截断 288 10.5 小结 289 第11章 高级套接字 290 11.1 unix域函数 290 11.1.1 unix域函数的地址结构 290 11.1.2 套接字函数 291 11.1.3 使用unix域函数进行套接字编程 291 11.1.4 传递文件描述符 293 11.1.5 socketpair()函数 294 11.1.6 传递文件描述符的例子 295 11.2 广播 299 11.2.1 广播的ip地址 300 11.2.2 广播与单播的比较 300 11.2.3 广播的示例 301 11.3 多播 307 11.3.1 多播的概念 308 11.3.2 广域网的多播 308 11.3.3 多播的编程 308 11.3.4 内核中的多播 310 11.3.5 一个多播例子的服务器端 313 11.3.6 一个多播例子的客户端 315 11.4 数据链路层访问 317 11.4.1 sock_packet类型 317 11.4.2 设置套接口以捕获链路帧的编程方法 317 11.4.3 从套接口读取链路帧的编程方法 318 11.4.4 定位ip包头的编程方法 319 11.4.5 定位tcp报头的编程方法 321 11.4.6 定位udp报头的编程方法 322 11.4.7 定位应用层报文数据的编程方法 323 11.4.8 使用sock_packet编写arp请求程序的例子 323 11.5 小结 326 第12章 套接字选项 328 12.1 获取和设置套接字选项getsocketopt()/setsocketopt() 328 12.1.1 getsockopt()函数和setsocketopt()函数的介绍 328 12.1.2 套接字选项 329 12.1.3 套接字选项简单示例 330 12.2 sol_socket协议族选项 334 12.2.1 so_broadcast广播选项 334 12.2.2 so_debug调试选项 335 12.2.3 so_dontroute不经过路由选项 335 12.2.4 so_error错误选项 335 12.2.5 so_keepalive保持连接选项 336 12.2.6 so_linger缓冲区处理方式选项 337 12.2.7 so_oobinline带外数据处理方式选项 339 12.2.8 so_rcvbuf和so_sndbuf缓冲区大小选项 340 12.2.9 so_rcvlowat和so_sndlowat缓冲区下限选项 340 12.2.10 so_rcvtimeo和so_sndtimeo收发超时选项 341 12.2.11 so_reuseraddr地址重用选项 341 12.2.12 so_exclusiveaddruse端口独占选项 342 12.2.13 so_type套接字类型选项 342 12.2.14 so_bsdcompat与bsd套接字兼容选项 342 12.2.15 so_bindtodevice套接字网络接口绑定选项 343 12.2.16 so_priority套接字优先级选项 344 12.3 ipproto_ip选项 344 12.3.1 ip_hdrincl选项 344 12.3.2 ip_optnios选项 344 12.3.3 ip_tos选项 344 12.3.4 ip_ttl选项 345 12.4 ipproto_tcp选项 345 12.4.1 tcp_keepalive选项 345 12.4.2 tcp_maxrt选项 346 12.4.3 tcp_maxseg选项 346 12.4.4 tcp_nodelay和tcp_cork选项 346 12.5 使用套接字选项 348 12.5.1 设置和获取缓冲区大小 348 12.5.2 获取套接字类型的例子 353 12.5.3 使用套接字选项的综合例子 353 12.6 ioctl()函数 358 12.6.1 ioctl()函数的命令选项 358 12.6.2 ioctl()函数的io请求 360 12.6.3 ioctl()函数的文件请求 362 12.6.4 ioctl()函数的网络接口请求 362 12.6.5 使用ioctl()函数对arp高速缓存操作 369 12.6.6 使用ioctl()函数发送路由表请求 371 12.7 fcntl()函数 371 12.7.1 fcntl()函数的选项 372 12.7.2 使用fcntl()函数修改套接字非阻塞属性 372 12.7.3 使用fcntl()函数设置信号属主 372 12.8 小结 373 第13章 原始套接字 374 13.1 概述 374 13.2 原始套接字的创建 375 13.2.1 sock_raw选项 375 13.2.2 ip_hdrincl套接字选项 376 13.2.3 不需要bind()函数 376 13.3 原始套接字发送报文 376 13.4 原始套接字接收报文 377 13.5 原始套接字报文处理时的结构 377 13.5.1 ip头部的结构 377 13.5.2 icmp头部结构 378 13.5.3 udp头部结构 381 13.5.4 tcp头部结构 382 13.6 ping的例子 384 13.6.1 协议格式 384 13.6.2 校验和函数 385 13.6.3 设置icmp发送报文的头部 386 13.6.4 剥离icmp接受报文的头部 387 13.6.5 计算时间差 388 13.6.6 发送报文 389 13.6.7 接收报文 390 13.6.8 主函数过程 391 13.6.9 主函数main() 393 13.6.10 编译测试 396 13.7 洪水攻击 396 13.8 icmp洪水攻击 397 13.8.1 icmp洪水攻击的原理 397 13.8.2 icmp洪水攻击的例子 397 13.9 udp洪水攻击 401 13.10 syn洪水攻击 405 13.10.1 syn洪水攻击的原理 405 13.10.2 syn洪水攻击的例子 405 13.11 小结 409 第14章 服务器模型选择 410 14.1 循环服务器 410 14.1.1 udp循环服务器 410 14.1.2 tcp循环服务器 413 14.2 简单并发服务器 415 14.2.1 并发服务器的模型 416 14.2.2 udp并发服务器 416 14.2.3 tcp并发服务器 419 14.3 tcp的高级并发服务器模型 421 14.3.1 单客户端单进程,统一accept() 422 14.3.2 单客户端单线程,统一accept() 425 14.3.3 单客户端单线程,各线程独自accept(),使用互斥锁 427 14.4 io复用循环服务器 431 14.4.1 io复用循环服务器模型介绍 431 14.4.2 io复用循环服务器模型的例子 432 14.5 小结 436 第15章 ipv6简介 437 15.1 ipv4的缺陷 437 15.2 ipv6的特点 438 15.3 ipv6的地址 439 15.3.1 ipv6的单播地址 439 15.3.2 可聚集全球单播地址 439 15.3.3 本地使用单播地址 440 15.3.4 兼容性地址 441 15.3.5 ipv6多播地址 441 15.3.6 ipv6任播地址 442 15.3.7 主机的多个ipv6地址 442 15.4 ipv6的头部 443 15.4.1 ipv6头部格式 443 15.4.2 与ipv4头部的对比 444 15.4.3 ipv6的tcp头部 444 15.4.4 ipv6的udp头部 444 15.4.5 ipv6的icmp头部 445 15.5 ipv6运行环境 447 15.5.1 加载ipv6模块 447 15.5.2 查看是否支持ipv6 447 15.6 ipv6的结构定义 448 15.6.1 ipv6的地址族和协议族 448 15.6.2 套接字地址结构 448 15.6.3 地址兼容考虑 450 15.6.4 ipv6通用地址 450 15.7 ipv6的套接字函数 451 15.7.1 socket()函数 451 15.7.2 没有发生改变的函数 451 15.7.3 发生改变的函数 452 15.8 ipv6的套接字选项 452 15.8.1 ipv6的套接字选项 452 15.8.2 单播跳限ipv6_unicast_hops 453 15.8.3 发送和接收多播包 454 15.8.4 ipv6中获得时间戳的ioctl命令 455 15.9 ipv6的库函数 455 15.9.1 地址转换函数的差异 455 15.9.2 域名解析函数的差异 455 15.9.3 测试宏 458 15.10 ipv6的编程的一个简单例子 458 15.10.1 服务器程序 458 15.10.2 客户端程序 460 15.10.3 编译调试 461 15.11 小结 462 第3篇 linux内核网络编程 第16章 linux内核中网络部分结构以及分布 464 16.1 概述 464 16.1.1 代码目录分布 464 16.1.2 内核中网络部分流程简介 466 16.1.3 系统提供修改网络流程点 468 16.1.4 sk_buff结构 469 16.1.5 网络协议数据结构inet_protosw 471 16.2 软中断cpu报文队列及其处理 473 16.2.1 linux内核网络协议层的层间传递手段——软中断 473 16.2.2 网络收发处理软中断的实现机制 475 16.3 socket数据如何在内核中接收和发送 476 16.3.1 socket()的初始化 476 16.3.2 接收网络数据recv() 476 16.3.3 发送网络数据send() 477 16.4 小结 477 第17章 netfilter框架内报文处理 478 17.1 netfilter 478 17.1.1 netfilter简介 478 17.1.2 netfilter框架 479 17.1.3 netfilter检查时的表格 480 17.1.4 netfilter的规则 480 17.2 iptables和netfilter 481 17.2.1 iptables简介 481 17.2.2 iptables的表和链 481 17.2.3 使用iptables设置过滤规则 483 17.3 内核模块编程 485 17.3.1 内核“hello world!”程序 485 17.3.2 内核模块的基本架构 487 17.3.3 内核模块加载和卸载过程 489 17.3.4 内核模块初始化和清理函数 490 17.3.5 内核模块初始化和清理过程的容错处理 490 17.3.6 内核模块编译所需的makefile 491 17.4 5个钩子点 492 17.4.1 netfilter的5个钩子点 492 17.4.2 nf_hook宏 493 17.4.3 钩子的处理规则 494 17.5 注册/注销钩子 494 17.5.1 结构nf_hook_ops 494 17.5.2 注册钩子 495 17.5.3 注销钩子 496 17.5.4 注册注销函数 497 17.6 钩子的简单处理例子 498 17.6.1 功能描述 498 17.6.2 需求分析 498 17.6.3 ping回显屏蔽实现 498 17.6.4 禁止向目的ip地址发送数据的实现 499 17.6.5 端口关闭实现 499 17.6.6 动态配置实现 499 17.6.7 可加载内核实现代码 501 17.6.8 应用层测试代码实现 508 17.6.9 编译运行 508 17.7 一点多个钩子的优先级 508 17.8 校验和问题 509 17.9 小结 510 第4篇 综 合 案 例 第18章 一个简单web服务器的例子shttpd 512 18.1 shttpd的需求分析 512 18.1.1 shttpd启动参数可动态配置的需求 513 18.1.2 shttpd的多客户端支持的需求 515 18.1.3 shttpd支持方法的需求 515 18.1.4 shttpd支持的http协议版本的需求 516 18.1.5 shttpd支持头部的需求 517 18.1.6 shttpd定位uri的需求 517 18.1.7 shttpd支持cgi的需求 518 18.1.8 shttpd错误代码的需求 519 18.2 shttpd的模块分析和设计 519 18.2.1 shttpd的主函数 520 18.2.2 shttpd命令行解析的分析设计 521 18.2.3 shttpd配置文件解析的分析设计 523 18.2.4 shttpd的多客户端支持的分析设计 523 18.2.5 shttpd头部解析的分析设计 526 18.2.6 shttpd对uri的分析设计 526 18.2.7 shttpd支持方法的分析设计 527 18.2.8 shttpd支持cgi的分析设计 527 18.2.9 shttpd错误处理的分析设计 530 18.3 shttpd各模块的实现 532 18.3.1 shttpd命令行解析的实现 532 18.3.2 shttpd文件配置解析的实现 535 18.3.3 shttpd的多客户端支持的实现 536 18.3.4 shttpd所请求uri解析的实现 540 18.3.5 shttpd方法解析的实现 541 18.3.6 shttpd响应方法的实现 541 18.3.7 shttpd支持cgi的实现 545 18.3.8 shttpd支持http协议版本的实现 548 18.3.9 shttpd内容类型的实现 548 18.3.10 shttpd错误处理的实现 550 18.3.11 shttpd生成目录下文件列表文件的实现 552 18.3.12 shttpd主函数的实现 554 18.4 shttpd的编译、调试和测试 555 18.4.1 建立源文件 555 18.4.2 制作makefile 555 18.4.3 制作执行文件 555 18.4.4 使用不同的浏览器测试服务器程序 556 18.5 小结 557 第19章 一个简单网络协议栈的例子sip 558 19.1 sip网络协议栈的功能描述 558 19.1.1 sip网络协议栈的基本功能描述 558 19.1.2 sip网络协议栈的分层功能描述 559 19.1.3 sip网络协议栈的用户接口功能描述 559 19.2 sip网络协议栈的架构 560 19.3 sip网络协议栈的存储区缓存 561 19.3.1 sip存储缓冲的结构定义 561 19.3.2 sip存储缓冲的处理函数 565 19.4 sip网络协议栈的网络接口层 567 19.4.1 sip网络接口层的架构 568 19.4.2 sip网络接口层的数据结构 568 19.4.3 sip网络接口层的初始化函数 570 19.4.4 sip网络接口层的输入函数 571 19.4.5 sip网络接口层的输出函数 574 19.5 sip网络协议栈的arp层 577 19.5.1 sip地址解析层的架构 577 19.5.2 sip地址解析层的数据结构 577 19.5.3 sip地址解析层的映射表 579 19.5.4 sip地址解析层的arp映射表维护函数 580 19.5.5 sip地址解析层的arp网络报文构建函数 581 19.5.6 sip地址解析层的arp网络报文收发处理函数 583 19.6 sip网络协议栈的ip层 586 19.6.1 sip网际协议层的架构 586 19.6.2 sip网际协议层的数据结构 587 19.6.3 sip网际协议层的输入函数 589 19.6.4 sip网际协议层的输出函数 593 19.6.5 sip网际协议层的分片函数 594 19.6.6 sip网际协议层的分片组装函数 595 19.7 sip网络协议栈的icmp层 599 19.7.1 sip控制报文协议的数据结构 599 19.7.2 sip控制报文协议协议支持 600 19.7.3 sip控制报文协议的输入函数 601 19.7.4 sip控制报文协议的回显应答函数 602 19.8 sip网络协议栈的udp层 603 19.8.1 sip数据报文层的数据结构 603 19.8.2 sip数据报文层的控制单元 603 19.8.3 sip数据报文层的输入函数 605 19.8.4 sip数据报文层的输出函数 606 19.8.5 sip数据报文层的建立函数 606 19.8.6 sip数据报文层的释放函数 607 19.8.7 sip数据报文层的绑定函数 607 19.8.8 sip数据报文层的发送数据函数 608 19.8.9 sip数据报文层的校验和计算 609 19.9 sip网络协议栈的协议无关层 610 19.9.1 sip协议无关层的系统架构 611 19.9.2 sip协议无关层的函数形式 611 19.9.3 sip协议无关层的接收数据函数 612 19.10 sip网络协议栈的bsd接口层 613 19.10.1 sip用户接口层的架构 613 19.10.2 sip用户接口层的套接字建立函数 613 19.10.3 sip用户接口层的套接字关闭函数 614 19.10.4 sip用户接口层的套接字绑定函数 614 19.10.5 sip用户接口层的套接字连接函数 615 19.10.6 sip用户接口层的套接字接收数据函数 615 19.10.7 sip用户接口层的发送数据函数 616 19.11 sip网络协议栈的编译 617 19.11.1 sip的文件结构 617 19.11.2 sip的makefile 618 19.11.3 sip的编译运行 618 19.12 小结 618 第20章 一个简单防火墙的例子sipfw 620 20.1 sipfw防火墙的功能描述 620 20.1.1 sipfw防火墙对主机进行网络数据过滤的功能描述 620 20.1.2 sipfw防火墙用户设置防火墙规则的功能描述 621 20.1.3 sipfw防火墙配置文件等附加功能的功能描述 621 20.2 sipfw需求分析 621 20.2.1 sipfw防火墙条件和动作 621 20.2.2 sipfw防火墙支持过滤的类型和内容 622 20.2.3 sipfw防火墙过滤的方式和动作 625 20.2.4 sipfw防火墙的配置文件 626 20.2.5 sipfw防火墙命令行配置格式 627 20.2.6 sipfw防火墙的规则文件格式 628 20.2.7 sipfw防火墙的日志文件数据格式 630 20.2.8 sipfw防火墙构建所采用的技术方案 630 20.3 使用netlink进行用户空间和内核空间数据交互 631 20.3.1 netlink的用户空间程序设计 632 20.3.2 netlink的内核空间api 635 20.4 使用proc进行内存数据用户空间映射 637 20.4.1 proc虚拟文件系统的结构 637 20.4.2 创建proc虚拟文件 638 20.4.3 删除proc虚拟文件 639 20.4.4 proc文件的写函数 639 20.4.5 proc文件的读函数 640 20.5 内核空间的文件操作函数 641 20.5.1 内核空间的文件结构 641 20.5.2 内核空间的文件建立操作 641 20.5.3 内核空间的文件读写操作 642 20.5.4 内核空间的文件关闭操作 643 20.6 sipfw防火墙的模块分析和设计 644 20.6.1 sipfw防火墙的总体架构 644 20.6.2 sipfw防火墙的用户命令解析 645 20.6.3 sipfw用户空间与内核空间的交互 649 20.6.4 sipfw防火墙内核链上的规则处理 651 20.6.5 sipfw防火墙的proc虚拟文件系统 654 20.6.6 sipfw防火墙的配置文件和日志文件处理 655 20.6.7 sipfw防火墙的过滤模块设计 657 20.7 sipfw防火墙各功能模块的实现 660 20.7.1 sipfw防火墙的命令解析代码 660 20.7.2 sipfw防火墙的过滤规则解析模块代码 664 20.7.3 sipfw防火墙的网络数据拦截模块代码 666 20.7.4 sipfw防火墙的proc虚拟文件系统 668 20.7.5 sipfw防火墙对配置文件的解析 670 20.7.6 sipfw防火墙内核模块初始化和退出 671 20.7.7 用户空间处理主函数 672 20.8 编译、调试和测试 673 20.8.1 用户程序和内核程序的makefile 673 20.8.2 编译及运行 674 20.8.3 下发过滤规则,测试过滤结果 674 20.9 小结 676

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jxwd

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值