c程序不会显示与显示相同的结果

时间:2013-08-28 22:05:36

标签: c file networking

我的C程序没有向文件写入与其显示的数据相同的数据。如何保存文件中输出到屏幕的内容。我正在尝试保存网页,文件名由第三个选项定义,[网站] [页面] [路径]

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>

int create_tcp_socket();
char *get_ip(char *host);
char *build_get_query(char *host, char *page);
void usage();

#define HOST "coding.debuntu.org"
#define PAGE "/"
#define PORT 80
#define USERAGENT "HTMLGET 1.0"
#define OS "mac osx"

int main(int argc, char **argv)
{
  struct sockaddr_in *remote;
  int sock;
  int tmpres;
  char *ip;
  char *get;
  char buf[BUFSIZ+1];
  char *host;
  char *page;
  char *HTMLfile;

  if(argc == 1){
    usage();
    exit(2);
  }  
  host = argv[1];
  if(argc > 2){
    page = argv[2];
  }else{
    page = PAGE;
  }
  HTMLfile = argv[3];

  sock = create_tcp_socket();
  ip = get_ip(host);
  fprintf(stderr, "<!--\nIP is %s\n", ip);
  remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
  remote->sin_family = AF_INET;
  tmpres = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr)));
  if( tmpres < 0)  
  {
    perror("Can't set remote->sin_addr.s_addr");
    exit(1);
  }else if(tmpres == 0)
  {
    fprintf(stderr, "%s is not a valid IP address\n", ip);
    exit(1);
  }
  remote->sin_port = htons(PORT);

  if(connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){
    perror("Could not connect");
    exit(1);
  }
  get = build_get_query(host, page);
  fprintf(stderr, "nQuery is:\n<<START>>\n%s<<END>>\n-->\n", get);

  //Send the query to the server
  int sent = 0;
  while(sent < strlen(get))
  {
    tmpres = send(sock, get+sent, strlen(get)-sent, 0);
    if(tmpres == -1){
      perror("Can't send query");
      exit(1);
    }
    sent += tmpres;
  }
  //now it is time to receive the page
  memset(buf, 0, sizeof(buf));
  int htmlstart = 0;
  char * htmlcontent;
  while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0){
    if(htmlstart == 0)
    {
      /* Under certain conditions this will not work.
      * If the \r\n\r\n part is splitted into two messages
      * it will fail to detect the beginning of HTML content
      */
      htmlcontent = strstr(buf, "\r\n\r\n");
      if(htmlcontent != NULL){
        htmlstart = 1;
        htmlcontent += 4;
      }
    }else{
      htmlcontent = buf;
    }
    if(htmlstart){
      fprintf(stdout, "%s", htmlcontent);
    }

    FILE *f;
    f = fopen(HTMLfile, "w");
    fprintf(f, "%s", htmlcontent); //stderr, "%s"
    fclose(f);

    memset(buf, 0, tmpres);
  }
  if(tmpres < 0)
  {
    perror("Error receiving data");
  }
  free(get);
  free(remote);
  free(ip);
  close(sock);
  return 0;
}

void usage()
{
  fprintf(stderr, "USAGE: htmlget host [page]\n\
\thost: the website hostname. ex: coding.debuntu.org\n\
\tpage: the page to retrieve. ex: index.html, default: /\n");
}


int create_tcp_socket()
{
  int sock;
  if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
    perror("Can't create TCP socket");
    exit(1);
  }
  return sock;
}


char *get_ip(char *host)
{
  struct hostent *hent;
  int iplen = 15; //XXX.XXX.XXX.XXX
  char *ip = (char *)malloc(iplen+1);
  memset(ip, 0, iplen+1);
  if((hent = gethostbyname(host)) == NULL)
  {
    herror("Can't get IP");
    exit(1);
  }
  if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
  {
    perror("Can't resolve host");
    exit(1);
  }
  return ip;
}

char *build_get_query(char *host, char *page)
{
  char *query;
  char *getpage = page;
  char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";
  if(getpage[0] == '/'){
    getpage = getpage + 1;
    fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", page, getpage);
  }
  // -5 is to consider the %s %s %s in tpl and the ending \0
  query = (char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(OS)+strlen(tpl)-5);
  sprintf(query, tpl, getpage, host, USERAGENT);
  return query;
//  FILE *f;
//  f = fopen(HTMLfile, "w");
//  fprintf(f, htmlcontent);
//  fclose(f);

}

这是我保存文件的地方:

FILE *f;
f = fopen(HTMLfile, "w");
fprintf(f, "%s", htmlcontent); //stderr, "%s"
fclose(f);

以下是为我的问题保存的结果(本页)

(['_setCustomVar', 1, 'tags', '|c|file|networking|']); 
_gaq.push(['_trackPageview']);
    var _qevents = _qevents || [];
    (function () {
        var ssl='https:'==document.location.protocol,
            s=document.getElementsByTagName('script')[0],
            ga=document.createElement('script');
        ga.type='text/javascript';
        ga.async=true;
        ga.src=(ssl?'https://ssl':'http://www')+'.google-analytics.com/ga.js';
        s.parentNode.insertBefore(ga,s);
        var sc=document.createElement('script');
        sc.type='text/javascript';
        sc.async=true;
        sc.src=(ssl?'https://secure':'http://edge')+'.quantserve.com/quant.js';
        s.parentNode.insertBefore(sc,s);
    })();
    _qevents.push({ qacct: "p-c1rF4kxgLUzNc" });
    </script>        

</body>
</html>

2 个答案:

答案 0 :(得分:1)

FILE *f;
f = fopen(HTMLfile, "w");
fprintf(f, "%s", htmlcontent); //stderr, "%s"
fclose(f);

不是每次通过循环打开和关闭文件,而是应该打开 它一次在循环之前,在你写入它时保持打开,然后关闭它 循环。

答案 1 :(得分:0)

不使用“w”打开文件,而是使用“a”。更好的是,只打开一次文件。

f = fopen(HTMLfile, "a");

w“写:为输出操作创建一个空文件。如果已存在同名文件,则丢弃其内容并将该文件视为新的空文件。

“a”追加:打开文件末尾的输出文件。输出操作总是在文件末尾写入数据,并将其扩展。重新定位操作(fseek,fsetpos,rewind)将被忽略。如果文件不存在,则创建该文件。