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

通常,请求数据的应用程序叫做客户端Client,而为请求服务叫做服务器Server。基本上说,首先,服务器监听一个端口,并且等待来自客户端的连接。之后客户端创建一个,并且尝试连接服务器。接着,服务器接受了来自客户端的连接,并且开始交换数据。一旦所有的数据都已经通过socket连接传输完毕,那么任意一方都可以关闭连接了。

我们的爬虫程序只需要client端就够了。

int build_connect(int *fd, char *ip, intport)
{
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (!inet_aton(ip, &(server_addr.sin_addr))) {
return -1;
} if ((*fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
return -1;
} if (connect(*fd, (struct sockaddr *)&server_addr, sizeof(structsockaddr_in)) < 0) {
close(*fd);
return -1;
} return 0;
}
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 recvEAGAIN?
* 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; /* moduluesfilter 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企业级项目实践之网络爬虫(28)——爬虫socket处理的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. Linux企业级项目实践之网络爬虫(3)——设计自己的网络爬虫

    网络抓取系统分为核心和扩展组件两部分.核心部分是一个精简的.模块化的爬虫实现,而扩展部分则包括一些便利的.实用性的功能.目标是尽量的模块化,并体现爬虫的功能特点.这部分提供简单.灵活的API,在基本不 ...

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

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

随机推荐

  1. .NET获取英文月份缩写名(可获取其他国家)

    来自: http://www.cnblogs.com/highend/archive/2010/03/16/1687126.html 今天在看本公司原有的项目代码当中 很不幸看到其中一些实现的部分代码 ...

  2. android系统的日志查看

    日志跟踪(alog) 在我们开发手机软件的过程中,常常需要通过USB线连接电脑看日志.但在windows下,我们要安装驱动.有的android板子,就不支持USB调试.所以我开发了这个小工具.方便打开 ...

  3. JBoss 系列九十六:JBoss MSC - 简介及一个简单演示样例

    什么是 JBoss MSC JBoss MSC 即 JBoss Modular Service Container,是第三代 JBoss 产品 JBoss 7和WildFfly的内核,JBoss MS ...

  4. 不相交集python实现

    1.不相交集是解决等价关系的一种数据结构,执行合并和查找的速度都很快,M次执行合并和查找的执行时间为(M*logN). 在一个集合中.对于每一对元素(a,b),a,b∈S,对于关系R假设满足以下三个条 ...

  5. apktool的下载地址

    googlecode将要关闭,代码转移到以下网址 http://ibotpeaches.github.io/Apktool/

  6. Java基础知识强化23:Java中数据类型转换(面试题)

    1. 以下代码输出结果是( D ).                     public  class  Test   {                                       ...

  7. ASP.NET页面周期

    上图为ASP.NET页面生命周期图. 以下详细讲解一下ASP.NET的页面生命周期.   请求页 请求页发生在页生命周期之前.用户请求时,ASP.NET将确定是否需要分析和编译页面,或者是否可以在不运 ...

  8. Windbg简单介绍

    1.1 使用帮助 Windbg中的命令分为三种:基本命令.元命令和扩展命令.基本命令和元命令都是调试器自带的,元命令以" ."开头. 扩展命令是外部加入的,以"!&quo ...

  9. drop表,然后创建表,插入数据,并创建索引等内容。

    execute immediate 'drop table sjb_jhgl_ydjhtdsbb';   execute immediate 'create table dw_sc.sjb_jhgl_ ...

  10. Oracle中REGEXP_SUBSTR函数(转)

    Oracle中REGEXP_SUBSTR函数 Oracle中REGEXP_SUBSTR函数的使用说明: 题目如下:在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20','2 ...