Web服务器的HTTP应答一般由以下几项构成:一个状态行,一个或多个应答头,一个空行,内容文档。设置HTTP应答头往往和设置状态行中的状态代码结合起来。例如,有好几个表示“文档位置已经改变”的状态代码都伴随着一个Location头,而401(Unauthorized)状态代码则必须伴随一个WWW-Authenticate头。
然而,即使在没有设置特殊含义的状态代码时,指定应答头也是很有用的。应答头可以用来完成:设置Cookie,指定修改日期,指示浏览器按照指定的间隔刷新页面,声明文档的长度以便利用持久HTTP连接,……等等许多其他任务。
设置应答头最常用的方法是HttpServletResponse的setHeader,该方法有两个参数,分别表示应答头的名字和值。和设置状态代码相似,设置应答头应该在发送任何文档内容之前进行。

HTTP应答头 说明:
Allow 服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length 表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入ByteArrayOutputStram,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。
Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires 应该在什么时候认为文档已经过期,从而不再缓存它?

void * recv_response(void * arg)
{
begin_thread(); int i, n, trunc_head = 0, len = 0;
char * body_ptr = NULL;
evso_arg * narg = (evso_arg *)arg;
Response *resp = (Response *)malloc(sizeof(Response));
resp->header = NULL;
resp->body = (char *)malloc(HTML_MAXLEN);
resp->body_len = 0;
resp->url = narg->url; regex_t re;
if (regcomp(&re, HREF_PATTERN, 0) != 0) {/* compile error */
SPIDER_LOG(SPIDER_LEVEL_ERROR, "compile regex error");
} SPIDER_LOG(SPIDER_LEVEL_INFO, "Crawling url: %s/%s", narg->url->domain, narg->url->path); while(1) {
/* what if content-length exceeds HTML_MAXLEN? */
n = read(narg->fd, resp->body + len, 1024);
if (n < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
/**
* TODO: Why always recv EAGAIN?
* should we deal EINTR
*/
//SPIDER_LOG(SPIDER_LEVEL_WARN, "thread %lu meet EAGAIN or EWOULDBLOCK, sleep", pthread_self());
usleep(100000);
continue;
}
SPIDER_LOG(SPIDER_LEVEL_WARN, "Read socket fail: %s", strerror(errno));
break; } else if (n == 0) {
/* finish reading */
resp->body_len = len;
if (resp->body_len > 0) {
extract_url(&re, resp->body, narg->url);
}
/* deal resp->body */
for (i = 0; i < (int)modules_post_html.size(); i++) {
modules_post_html[i]->handle(resp);
} break; } else {
//SPIDER_LOG(SPIDER_LEVEL_WARN, "read socket ok! len=%d", n);
len += n;
resp->body[len] = '\0'; if (!trunc_head) {
if ((body_ptr = strstr(resp->body, "\r\n\r\n")) != NULL) {
*(body_ptr+2) = '\0';
resp->header = parse_header(resp->body);
if (!header_postcheck(resp->header)) {
goto leave; /* modulues filter fail */
}
trunc_head = 1; /* cover header */
body_ptr += 4;
for (i = 0; *body_ptr; i++) {
resp->body[i] = *body_ptr;
body_ptr++;
}
resp->body[i] = '\0';
len = i;
}
continue;
}
}
} leave:
close(narg->fd); /* close socket */
free_url(narg->url); /* free Url object */
regfree(&re); /* free regex object */
/* free resp */
free(resp->header->content_type);
free(resp->header);
free(resp->body);
free(resp); end_thread();
return NULL;
}

Linux企业级项目实践之网络爬虫(12)——处理HTTP应答头的更多相关文章

  1. Linux企业级项目实践之网络爬虫(1)——项目概述及准备工作

    我们在学习了Linux系统编程之后,需要一些实战项目来提高自己的水平,本系列我们通过编写一个爬虫程序,将我们学习的知识进行综合应用,同时在实现项目的过程中逐渐养成一些有用的思维方式,并具有初步的软件开 ...

  2. Linux企业级项目实践之网络爬虫(29)——遵守robots.txt

    Robots协议(也称为爬虫协议.机器人协议等)的全称是"网络爬虫排除标准"(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以 ...

  3. Linux企业级项目实践之网络爬虫(21)——扩展为多任务爬虫

    高效的网络爬虫是搜索引擎的重要基础.采用多任务并发执行,实现类似于CPU的流水线(pipeline)运行方式,可极大地提高网络和计算资源的利用率等性能. #include "threads. ...

  4. Linux企业级项目实践之网络爬虫(2)——网络爬虫的结构与工作流程

    网络爬虫是捜索引擎抓取系统的重要组成部分.爬虫的主要目的是将互联网上的网页下载到本地形成一个或联网内容的镜像备份. 一个通用的网络爬虫的框架如图所示:

  5. Linux企业级项目实践之网络爬虫(23)——系统测试:找出系统中的bug

    为了验证爬虫的业务流程.性能和健壮性需要进行测试. 软件测试是描述一种用来促进鉴定软件的正确性.完整性.安全性和质量的过程.软件测试的经典定义是:在规定的条件下对程序进行操作,以发现程序错误,衡量软件 ...

  6. Linux企业级项目实践之网络爬虫(30)——通过查阅RFC文档扩充更加复杂的功能

    HTTP是一种很简单的请求.响应式协议,客户端发送一个请求.服务器返回一个响应.HTTP 1.1 版本规范由 RFC2616 定义.了解了 HTTP请求.响应消息在TCP数据流中的格式,很容易使用纯 ...

  7. Linux企业级项目实践之网络爬虫(28)——爬虫socket处理

    Socket是进程之间交换数据的机制.这些进程即可以是同一台机器上的,也可以是通过网络连接起来的不同机器.一旦一个Socket连接建立,那么数据就能够双向传输,直到其中一端关闭连接. 通常,请求数据的 ...

  8. Linux企业级项目实践之网络爬虫(19)——epoll接口

    由于要实现爬虫程序的快速抓取,显然如果采用阻塞型的I/O方式,那么系统可能很长时间都处在等待内核响应的状态中,这样爬虫程序将大大地降低效率.然而,如果采用非阻塞I/O,那么就要一直调用应用进程,反复对 ...

  9. Linux企业级项目实践之网络爬虫(6)——将程序设计成为守护进程

    在linux或者unix操作系统中在系统的引导的时候会开启很多服务,这些服务就叫做守护进程.为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统. ...

随机推荐

  1. cpppp

  2. JS-string内置对象

    1.charCodeAt方法返回一个整数,代表指定位置字符的Unicode编码. strObj.charCodeAt(index) 说明: index将被处理字符的从零开始计数的编号.有效值为0到字符 ...

  3. Python偏函数实例

    目标: 1.编写一个gui,生成按钮 2.通过偏函数,生成按钮 3.通过装饰器,实现按钮输出信息功能 1.使用Tkinter,创建一个按钮 代码如下: handetiandeMacBook-Pro:~ ...

  4. Maven相关介绍

    Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Depen ...

  5. 前端input选中状态时的蓝框

    input标签在选中状态时,我们的浏览器不同时,会有不同效果. 一般我们chrome时可能会没有这个效果,但是如果是safari时,这个效果就... 这时为了达到效果统一,我们不得不去掉这个蓝框,就要 ...

  6. bootstrap data

    bootstrap data 用法 <div data-role="page" data-last-value="43" data-hidden=&quo ...

  7. Linux命令之exit

    本文链接:http://codingstandards.iteye.com/blog/836625   (转载请注明出处) 用途说明 exit命令用于退出当前shell,在shell脚本中可以终止当前 ...

  8. 二、UITableView和它的亲戚们

    . UITableView 参考: https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableView ...

  9. 国外.net学习资源网站

    转载 :出处:http://www.cnblogs.com/kingjiong/ 名称:快速入门地址 http://chs.gotdotnet.com/quickstart/ 描述:本站点是微软.NE ...

  10. C#、.NET和ASP.NET三者之间的区别

    刚毕业后出去找工作面试的时候就遇到这个问题!.回答不上来.回来网上查的如下: 那么 .NET.C#和ASP.NET这三者之间区别不清楚,到底它们之间有什么联系呢? 1..NET是一个平台,一个抽象的平 ...