⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multi.c

📁 harvest是一个下载html网页得机器人
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** *                                  _   _ ____  _      *  Project                     ___| | | |  _ \| |     *                             / __| | | | |_) | |     *                            | (__| |_| |  _ <| |___  *                             \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. *  * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id: multi.c,v 1.39 2003/10/18 20:38:18 bagder Exp $ ***************************************************************************/#include "setup.h"#include <stdlib.h>#include <string.h>#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <curl/curl.h>#include "urldata.h"#include "transfer.h"#include "url.h"#include "connect.h"#include "progress.h"/* The last #include file should be: */#ifdef CURLDEBUG#include "memdebug.h"#endifstruct Curl_message {  /* the 'CURLMsg' is the part that is visible to the external user */  struct CURLMsg extmsg;  struct Curl_message *next;};typedef enum {  CURLM_STATE_INIT,  CURLM_STATE_CONNECT,     /* resolve/connect has been sent off */  CURLM_STATE_WAITRESOLVE, /* we're awaiting the resolve to finalize */  CURLM_STATE_WAITCONNECT, /* we're awaiting the connect to finalize */  CURLM_STATE_DO,          /* send off the request (part 1) */  CURLM_STATE_DO_MORE,     /* send off the request (part 2) */  CURLM_STATE_PERFORM,     /* transfer data */  CURLM_STATE_DONE,        /* post data transfer operation */  CURLM_STATE_COMPLETED,   /* operation complete */  CURLM_STATE_LAST /* not a true state, never use this */} CURLMstate;struct Curl_one_easy {  /* first, two fields for the linked list of these */  struct Curl_one_easy *next;  struct Curl_one_easy *prev;    struct SessionHandle *easy_handle; /* the easy handle for this unit */  struct connectdata *easy_conn;     /* the "unit's" connection */  CURLMstate state;  /* the handle's state */  CURLcode result;   /* previous result */  struct Curl_message *msg; /* A pointer to one single posted message.                               Cleanup should be done on this pointer NOT on                               the linked list in Curl_multi.  This message                               will be deleted when this handle is removed                               from the multi-handle */  int msg_num; /* number of messages left in 'msg' to return */};#define CURL_MULTI_HANDLE 0x000bab1e#define GOOD_MULTI_HANDLE(x) ((x)&&(((struct Curl_multi *)x)->type == CURL_MULTI_HANDLE))#define GOOD_EASY_HANDLE(x) (x)/* This is the struct known as CURLM on the outside */struct Curl_multi {  /* First a simple identifier to easier detect if a user mix up     this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */  long type;  /* We have a linked list with easy handles */  struct Curl_one_easy easy;   /* This is the amount of entries in the linked list above. */  int num_easy;  int num_msgs; /* total amount of messages in the easy handles */  /* Hostname cache */  curl_hash *hostcache;};CURLM *curl_multi_init(void){  struct Curl_multi *multi;  multi = (void *)malloc(sizeof(struct Curl_multi));  if(multi) {    memset(multi, 0, sizeof(struct Curl_multi));    multi->type = CURL_MULTI_HANDLE;  }  multi->hostcache = Curl_hash_alloc(7, Curl_freednsinfo);  if(!multi->hostcache) {    /* failure, free mem and bail out */    free(multi);    multi = NULL;  }  return (CURLM *) multi;}CURLMcode curl_multi_add_handle(CURLM *multi_handle,                                CURL *easy_handle){  struct Curl_multi *multi=(struct Curl_multi *)multi_handle;  struct Curl_one_easy *easy;  /* First, make some basic checks that the CURLM handle is a good handle */  if(!GOOD_MULTI_HANDLE(multi))    return CURLM_BAD_HANDLE;    /* Verify that we got a somewhat good easy handle too */  if(!GOOD_EASY_HANDLE(easy_handle))    return CURLM_BAD_EASY_HANDLE;  /* Now, time to add an easy handle to the multi stack */  easy = (struct Curl_one_easy *)malloc(sizeof(struct Curl_one_easy));  if(!easy)    return CURLM_OUT_OF_MEMORY;    /* clean it all first (just to be sure) */  memset(easy, 0, sizeof(struct Curl_one_easy));  /* set the easy handle */  easy->easy_handle = easy_handle;  easy->state = CURLM_STATE_INIT;  /* for multi interface connections, we share DNS cache automaticly */  easy->easy_handle->hostcache = multi->hostcache;    /* We add this new entry first in the list. We make our 'next' point to the     previous next and our 'prev' point back to the 'first' struct */  easy->next = multi->easy.next;  easy->prev = &multi->easy;   /* make 'easy' the first node in the chain */  multi->easy.next = easy;  /* if there was a next node, make sure its 'prev' pointer links back to     the new node */  if(easy->next)    easy->next->prev = easy;  /* increase the node-counter */  multi->num_easy++;  return CURLM_CALL_MULTI_PERFORM;}CURLMcode curl_multi_remove_handle(CURLM *multi_handle,                                   CURL *curl_handle){  struct Curl_multi *multi=(struct Curl_multi *)multi_handle;  struct Curl_one_easy *easy;  /* First, make some basic checks that the CURLM handle is a good handle */  if(!GOOD_MULTI_HANDLE(multi))    return CURLM_BAD_HANDLE;    /* Verify that we got a somewhat good easy handle too */  if(!GOOD_EASY_HANDLE(curl_handle))    return CURLM_BAD_EASY_HANDLE;  /* scan through the list and remove the 'curl_handle' */  easy = multi->easy.next;  while(easy) {    if(easy->easy_handle == curl_handle)      break;    easy=easy->next;  }  if(easy) {    /* If the 'state' is not INIT or COMPLETED, we might need to do something       nice to put the easy_handle in a good known state when this returns. */    /* clear out the usage of the shared DNS cache */    easy->easy_handle->hostcache = NULL;        /* make the previous node point to our next */    if(easy->prev)      easy->prev->next = easy->next;    /* make our next point to our previous node */    if(easy->next)      easy->next->prev = easy->prev;        /* NOTE NOTE NOTE       We do not touch the easy handle here! */    if (easy->msg)      free(easy->msg);    free(easy);    multi->num_easy--; /* one less to care about now */    return CURLM_OK;  }  else    return CURLM_BAD_EASY_HANDLE; /* twasn't found */}CURLMcode curl_multi_fdset(CURLM *multi_handle,                           fd_set *read_fd_set, fd_set *write_fd_set,                           fd_set *exc_fd_set, int *max_fd){  /* Scan through all the easy handles to get the file descriptors set.     Some easy handles may not have connected to the remote host yet,     and then we must make sure that is done. */  struct Curl_multi *multi=(struct Curl_multi *)multi_handle;  struct Curl_one_easy *easy;  int this_max_fd=-1;  if(!GOOD_MULTI_HANDLE(multi))    return CURLM_BAD_HANDLE;  *max_fd = -1; /* so far none! */  easy=multi->easy.next;  while(easy) {    switch(easy->state) {    default:      break;    case CURLM_STATE_WAITRESOLVE:      /* waiting for a resolve to complete */      Curl_multi_ares_fdset(easy->easy_conn, read_fd_set, write_fd_set,                            &this_max_fd);      if(this_max_fd > *max_fd)        *max_fd = this_max_fd;      break;    case CURLM_STATE_WAITCONNECT:    case CURLM_STATE_DO_MORE:      {        /* when we're waiting for a connect, we wait for the socket to           become writable */        struct connectdata *conn = easy->easy_conn;        int sockfd;        if(CURLM_STATE_WAITCONNECT == easy->state) {          sockfd = conn->firstsocket;          FD_SET(sockfd, write_fd_set);        }        else {          /* When in DO_MORE state, we could be either waiting for us             to connect to a remote site, or we could wait for that site             to connect to us. It makes a difference in the way: if we             connect to the site we wait for the socket to become writable, if              the site connects to us we wait for it to become readable */          sockfd = conn->secondarysocket;          FD_SET(sockfd, write_fd_set);        }        if(sockfd > *max_fd)          *max_fd = sockfd;      }      break;    case CURLM_STATE_PERFORM:      /* This should have a set of file descriptors for us to set.  */      /* after the transfer is done, go DONE */      Curl_single_fdset(easy->easy_conn,                        read_fd_set, write_fd_set,                        exc_fd_set, &this_max_fd);      /* remember the maximum file descriptor */      if(this_max_fd > *max_fd)        *max_fd = this_max_fd;      break;    }    easy = easy->next; /* check next handle */  }  return CURLM_OK;}CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles){  struct Curl_multi *multi=(struct Curl_multi *)multi_handle;  struct Curl_one_easy *easy;  bool done;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -