好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

用c socket 方式下载网页

用c socket 方式下载网页

 tmpfile="abc.txt";
//******************* 处理命令行的参数 *************************

 if(argc<2)      //参数不足
 { printf("%s","/n/nExp: ./client  http://192.168.1.254:80  /n/n");
  exit(1);
 }
 if(!(tempStr=strstr(argv[1],"http://")))   //必须以 http://开头
 { printf("parameter error!/n");
  exit(0);
 }
 strcpy(web_domain.url,tempStr);      //http://www.xh88.com:80/index.php
 strcpy(web_domain.host,web_domain.url+7);   //www.xh88.com
 //处理 host
 if((tempStr=strstr(web_domain.host,"/")))
 { *tempStr='/0';         //web_domain.host 里去除:后的东西
 }
 if((tempStr=strstr(web_domain.host,":")))
 { *tempStr='/0';         //Host 里去除:后的东西
  web_domain.port=atoi(tempStr+1);    //改写端口
 }
//!
printf("%s/n%d/n%s/n",web_domain.host,web_domain.port,web_domain.url);

 hostbyname = gethostbyname(web_domain.host);  //将基本名字和地址转换
 if((sock_id=socket(PF_INET,SOCK_STREAM,0))==-1)
 { perror("socket");
  exit(1);
 }

//初始化远端要传递的socket
 remote_addr.sin_family=AF_INET;      //地址族
 remote_addr.sin_port=htons(web_domain.port);  //端口号
 remote_addr.sin_addr=*((struct in_addr *)hostbyname->h_addr);  //IP地址
 bzero(&(remote_addr.sin_zero),8);     //填充0 以保持与struct sockaddr同样大小

//和服务器建立连接
 if(connect(sock_id,(struct sockaddr *)&remote_addr,sizeof(remote_addr))==-1)
 { perror("connect");
  exit(1);
 }
printf("/n/nconnected %s:%d ok!/n/n",web_domain.url,web_domain.port);

//创建要发送给远端的字串
 sprintf(send_str,"GET %s HTTP/1.1/nAccept: */*/nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)/nHost: %s/n/n",web_domain.url,web_domain.host);
 printf("%s/n/n",send_str);
//开始向服务器发送数据
 if(send(sock_id,send_str,strlen(send_str),0)==-1)
 { perror("send");
  exit(1);
 }
 recBuf=malloc(MaxRecvLen);  //为储存远端返回的字串的变量申请空间
 //fp=fopen(tmpfile,"w");
 while(1)
 {

//设置无堵塞模式
  FD_ZERO(&sockid_readable);
  FD_SET(sock_id,&sockid_readable);
  select(sock_id+1, &sockid_readable, NULL, NULL, &timeout);
  if (!FD_ISSET(sock_id, &sockid_readable))
  { printf("Timed out./n");
   break;
  }
  recv_numb = recv(sock_id,recBuf,MaxRecvLen,0); //得到远端返回的字串
  recBuf[recv_numb]='/0';

  //fputs(fp,);
  // fp=fopen(tmpfile,"w");
  printf("/n/t********* %d *******",recv_numb);
  printf("%s",recBuf);
  if(recv_numb<1)  //返回的长度不够退出循环
   break;
 }

 printf("/n/nrecv  ok!/n/n");
 close(sock_id);
 return 0;
}


socket下载网页时网络阻塞

      2006-9-25 00:00

提问者: songma931   |   悬赏分:20   |   浏览次数:1735次

我用socket写了个小程序,用来下载一个网页的HTML文件,connect和connect以前都没有问题,当recv的返回值是0的时候,就显示下载完毕.
我用它来下mail.163.com的HTML的时候,什么问题也没有,但如果用来下zhidao.baidu.com的HTML的时候,明明整个HTML都下载下来了,可它却不马上显示下载完毕,停在recv(),要过一些时间才显示下载完毕.
哪位大虾给解释一下啊.它在停下的这一些时间里做什么,以及怎么避免这种情况发生.没时间大体给分析一下也可以啊.

检举   |   2006-10-1 14:59

  最佳答案

这个问题涉及到HTTP协议。

估计zhidao默认是以KeepAlive的方式处理HTTP请求的,就是说服务器端会保持连接一段时间,以便重新利用该连接接受新的HTTP请求。

解决的办法是 
1. 发送HTTP请求的时候主动要求不使用KeepAlive;
2. 或者对服务器返回的内容做分析,根据返回的头部信息能够知道数据的长度或者数据块的大小和数目(如果是以Transfer-Encoding: chunked的方式返回),这样就能确定是否已经接受了所有的数据,然后进行主动close().

另外补充一下: 自己写socket程序下载网页会涉及到很多问题,比如有些服务器是把数据压缩后返回的,比如google的有些服务,你还需要对它进行解压还原。
因此,建议使用一些已有的库进行开发会比较方便一点,推荐使用libcurl来处理HTTP/FTP。

查看更多关于用c socket 方式下载网页的详细内容...

  阅读:41次