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

📄 http_resp.c

📁 完整实现http协议源代码(WINDOWS或LINUX平台均可移植使用),我在VC++上(不调用WINDOWS的HTTP的API)可实现XML文件下载等.
💻 C
📖 第 1 页 / 共 2 页
字号:
	}    }  /* clip the buffer */  http_trans_buf_clip(a_conn, l_start_body + 4); ec:  a_resp->header_state = http_resp_header_start;  return l_return;}inthttp_resp_read_body(http_resp *a_resp,		    http_req *a_req,		    http_trans_conn *a_conn){  int      l_return = 0;  char    *l_content_length = NULL;  char    *l_transfer_encoding = NULL;  char    *l_connection = NULL;  /* check to see if we have to jump in anywhere. */  if (a_conn->sync == HTTP_TRANS_ASYNC)    {      if (a_resp->body_state == http_resp_body_read_content_length)	goto http_resp_body_read_content_length_jump;      if (a_resp->body_state == http_resp_body_read_chunked)	goto http_resp_body_read_chunked_jump;      if (a_resp->body_state == http_resp_body_read_standard)	goto http_resp_body_read_standard_jump;    }  /* check to make sure that things are ok. */  if ((!a_resp) || (!a_conn))    return -1;  /* check to see if there should be an entity body. */  /* check to see if there's a content length */  l_content_length =    http_hdr_get_value(a_resp->headers,		       http_hdr_Content_Length);  /* check to see if there's a transfer encoding */  l_transfer_encoding =    http_hdr_get_value(a_resp->headers,		       http_hdr_Transfer_Encoding);  /* check to see if the connection header is set */  l_connection =     http_hdr_get_value(a_resp->headers,		       http_hdr_Connection);  /* if there's a content length, do your stuff */  if (l_content_length && (a_req->type != http_req_type_head))    {      if (string_is_number(l_content_length) == 0)	{	  a_conn->errstr = "Content length in http response was not a number";	  return -1;	}      a_resp->content_length = atoi(l_content_length);      /* set the state */      a_resp->body_state = http_resp_body_read_content_length;    http_resp_body_read_content_length_jump:      l_return = read_body_content_length(a_resp, a_req, a_conn);    }  else if (l_content_length)    {      /* this happens in a head request with content length. */      return HTTP_TRANS_DONE;    }  else if (l_transfer_encoding)    {      /* check to see if it's using chunked transfer encoding */      if (!strcasecmp(l_transfer_encoding, "chunked"))	{	  /* set the state */	  a_resp->body_state = http_resp_body_read_chunked;	http_resp_body_read_chunked_jump:	  l_return = read_body_chunked(a_resp, a_req, a_conn);	}      else	{	  /* what kind of encoding? */	  a_conn->errstr = "Unknown encoding type in http response";	  return -1;	}    }  else    {      a_resp->body_state = http_resp_body_read_standard;      /* set the state */    http_resp_body_read_standard_jump:      l_return = read_body_standard(a_resp, a_req, a_conn);      /* after that the connection gets closed */      if (l_return == HTTP_TRANS_DONE)	{	  close(a_conn->sock);	  a_conn->sock = -1;	}    }  /* check to see if the connection should be closed */  if (l_connection && (l_return != HTTP_TRANS_NOT_DONE))    {      if (!strcasecmp(l_connection, "close"))	{	  close (a_conn->sock);	  a_conn->sock = -1;	}    }  if (l_return == HTTP_TRANS_DONE)    a_resp->body_state = http_resp_body_start;  return l_return;}static intstring_is_number(char *a_string){  int i = 0;    if (strlen(a_string) < 1)    return 0;  while (a_string[i])    {      if (isdigit(a_string[i]) == 0)	return 0;      i++;    }  return 1;}static intread_chunk(http_trans_conn *a_conn){  char *l_end_chunk_hdr = NULL;  int   l_len = 0;  int   i = 0;  int   j = 0;  char *l_ptr = NULL;  int   l_left_to_read = 0;  int   l_rv = 0;  if (a_conn->chunk_len == 0)    {      /* check to make sure that the pattern is in the	 buffer */      do {	if ((l_end_chunk_hdr =	     http_trans_buf_has_patt(a_conn->io_buf, a_conn->io_buf_alloc,				     "\r\n", 2)) == NULL)	  {	    l_rv = http_trans_read_into_buf(a_conn);	    if (l_rv == HTTP_TRANS_ERR)	      return HTTP_TRANS_ERR;	    /* check to see if the remote end hung up. */	    if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))	      return HTTP_TRANS_ERR;	    if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))	      return HTTP_TRANS_NOT_DONE;	  }      } while (l_end_chunk_hdr == NULL);      /* set the begining at the start of the buffer */      l_ptr = a_conn->io_buf;      /* eat the hex value of the chunk */      while ((l_ptr < l_end_chunk_hdr) &&	     (((tolower(*l_ptr) <= 'f') && (tolower(*l_ptr) >= 'a')) ||	      ((*l_ptr <= '9') && (*l_ptr >= '0'))))	l_ptr++;      /* get the length of the hex number */      l_len = l_ptr - a_conn->io_buf;      if (l_len == 0)	{	  a_conn->chunk_len = -1;	  return HTTP_TRANS_ERR;	}      /* walk the size adding the values as you go along. */      for (i=0, j=l_len-1; i < l_len; i++, j--)	{	  if ((tolower(a_conn->io_buf[i]) <= 'f') && (tolower(a_conn->io_buf[i]) >= 'a'))	    a_conn->chunk_len += (tolower(a_conn->io_buf[i]) - 0x57) << (4*j);	  else	    a_conn->chunk_len += (tolower(a_conn->io_buf[i]) - 0x30) << (4*j);	}      /* reset the pointer past the end of the header */      http_trans_buf_clip(a_conn, l_end_chunk_hdr + 2);    }  /* check to see if it's the last chunk.  If not then add it.*/  if (a_conn->chunk_len != 0)    {      /* figure out how much we need to read */      /* the + 2 is for the \r\n that always follows a chunk. */      l_left_to_read = a_conn->chunk_len - a_conn->io_buf_alloc + 2;      /* check to make sure that we actually need to read anything in. */      if (l_left_to_read > 0)	{	  /* set the vars in the struct */	  a_conn->io_buf_io_left = l_left_to_read;	  a_conn->io_buf_io_done = 0;	  /* append it */	  do {	    l_rv = http_trans_read_into_buf(a_conn);	    if (l_rv == HTTP_TRANS_ERR)	      return HTTP_TRANS_ERR;	    /* check and see if the server hung up. */	    if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))	      return HTTP_TRANS_ERR;	    if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))	      return HTTP_TRANS_NOT_DONE;	  } while (l_rv == HTTP_TRANS_NOT_DONE);	}    }  if (a_conn->io_buf_alloc >= a_conn->chunk_len + 2)    return HTTP_TRANS_DONE;  /* we only get here if there was an error. */  if (a_conn->chunk_len == 0)    return HTTP_TRANS_DONE;  return HTTP_TRANS_ERR;}static intread_body_chunked(http_resp *a_resp,		  http_req *a_req,		  http_trans_conn *a_conn){  int   l_rv = 0;  int   l_done = 0;    do    {      /* read a chunk */      l_rv = read_chunk(a_conn);      if (l_rv == HTTP_TRANS_ERR)	return HTTP_TRANS_ERR;      if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))	return HTTP_TRANS_NOT_DONE;      /* see if it's the first time */      if (a_conn->chunk_len > 0)	{	  if (a_resp->body == NULL)	    {	      a_resp->body = malloc(a_conn->chunk_len);	      memcpy(a_resp->body, a_conn->io_buf, a_conn->chunk_len);	      a_resp->body_len = a_conn->chunk_len;	    }	  /* append it to the body */	  else	    {	      a_resp->body = realloc(a_resp->body,				     (a_resp->body_len + a_conn->chunk_len));	      memcpy(&a_resp->body[a_resp->body_len], a_conn->io_buf, a_conn->chunk_len);	      a_resp->body_len += a_conn->chunk_len;	    }	}      /* make sure there's at least 2 bytes in the buffer.	 This happens when a read was 3 bytes as in 0\r\n	 and there is still 2 bytes ( \r\n ) in the read queue. */      if ((a_conn->chunk_len == 0) && (a_conn->io_buf_alloc < 2))	{	  a_conn->io_buf_io_left = ( 2 - a_conn->io_buf_alloc );	  a_conn->io_buf_io_done = 0;	  do {	    l_rv = http_trans_read_into_buf(a_conn);	  } while (l_rv == HTTP_TRANS_NOT_DONE);	  /* check for an error */	  if (l_rv == HTTP_TRANS_ERR)	    return HTTP_TRANS_ERR;	}      if (a_conn->chunk_len == 0)	l_done = 1;      else	{	  /* clip the buffer */	  http_trans_buf_clip(a_conn, &a_conn->io_buf[a_conn->chunk_len + 2]);	}      a_conn->chunk_len = 0;    } while (l_done == 0);  return HTTP_TRANS_DONE;}static voidflush_response_body(http_resp *a_resp,                    http_trans_conn *a_conn){  if (a_resp->body != NULL) {    free(a_resp->body);  }  a_resp->flushed_length += a_resp->body_len;  a_resp->body_len = a_conn->io_buf_alloc;  a_resp->body = malloc(a_conn->io_buf_alloc + 1);  memset(a_resp->body, 0, a_conn->io_buf_alloc + 1);  memcpy(a_resp->body, a_conn->io_buf, a_conn->io_buf_alloc);  /* clean the buffer */  http_trans_buf_reset(a_conn);}voidhttp_resp_flush(http_resp *a_resp,                http_trans_conn *a_conn){  flush_response_body(a_resp, a_conn);}static intread_body_content_length(http_resp *a_resp,			 http_req *a_req,			 http_trans_conn *a_conn){  int l_len = 0;  int l_left_to_read = 0;  int l_rv = 0;  l_len = a_resp->content_length;  if (l_len == 0)    return HTTP_TRANS_DONE;  /* find out how much more we have to read */  l_left_to_read = l_len - a_conn->io_buf_alloc - a_resp->flushed_length - a_resp->body_len;  /* set the variables */  a_conn->io_buf_io_left = l_left_to_read;  a_conn->io_buf_io_done = 0;  if (l_left_to_read > 0)    {      /* append the rest of the body to the	 buffer */      do {	l_rv = http_trans_read_into_buf(a_conn);	if ((l_rv == HTTP_TRANS_NOT_DONE) && 	    (a_conn->sync == HTTP_TRANS_ASYNC))	  return HTTP_TRANS_NOT_DONE;	if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))	  return HTTP_TRANS_ERR;      } while(l_rv == HTTP_TRANS_NOT_DONE);      if (l_rv == HTTP_TRANS_ERR)	return HTTP_TRANS_ERR;    }  /* write it into the body */  flush_response_body (a_resp, a_conn);  return HTTP_TRANS_DONE;}static intread_body_standard(http_resp *a_resp,		   http_req *a_req,		   http_trans_conn *a_conn){  int l_rv = 0;  /* anything without a content length or chunked encoding */  do {    l_rv = http_trans_read_into_buf(a_conn);    if (a_conn->sync == HTTP_TRANS_ASYNC)      {	if ((l_rv == HTTP_TRANS_NOT_DONE) || (a_conn->last_read != 0))	  return HTTP_TRANS_NOT_DONE;      }  } while ((l_rv == HTTP_TRANS_NOT_DONE) || (a_conn->last_read > 0));  if (l_rv == HTTP_TRANS_ERR)    return HTTP_TRANS_ERR;  flush_response_body(a_resp, a_conn);  return HTTP_TRANS_DONE;}

⌨️ 快捷键说明

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