zoukankan      html  css  js  c++  java
  • Linux企业级项目实践之网络爬虫(28)——爬虫socket处理


    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] = '';
     
               if (!trunc_head) {
                    if ((body_ptr =strstr(resp->body, "
    
    ")) != NULL) {
                        *(body_ptr+2) = '';
                        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] = '';
                        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;
    }

  • 相关阅读:
    AN BD FD DD CD UT CT TT IT ST UAT OP
    log4j
    重构代码
    with as sql的优化
    svn locked,并且无法clean up 的解决方法
    去掉Eclipse中没用的workspace
    getHibernateTemplate()的get方法
    Java反射
    windows 右键新建html文档
    fiddler 针对单个接口打断点
  • 原文地址:https://www.cnblogs.com/new0801/p/6176980.html
Copyright © 2011-2022 走看看