C语言实现Web客户端

http://blog.sina.com.cn/s/blog_4b73e760010007ie.html

C语言实现Web客户端

  (2007-01-23 21:41:54)
  分类: 学习心得
和我的上一篇文章是一起写的,呵呵,大家给提点意见啊。
 
:-)
 
/*********filename : Client.cpp****************
       该程序通过标准socket实现HTTP/1.0协议     
  运行该程序可以通过GET 方法取得Head域并将   
  所请求的内容存储到本地                                       
**********************************************/
#include <winsock.h>
#include <iostream>
#define HTTP_PORT 80              //HTTP连接的默认端口号
#define MAXSIZE 256                //自定义的每次传输数据的最大数量
using namespace std;
/*
  * 这个方法构造本地SOCKET
  * @return
    返回构造好的socket描述符
  */
int make_socket() {
  struct sockaddr_in local_addr;        //该结构体存储本地地址信息
  int tempSockId;                //临时变量 用来暂时存储socket描述符
  tempSockId = socket(PF_INET, SOCK_STREAM, 0);
  if (tempSockId == -1) {            //如果返回值为-1 则出错
    return tempSockId;
  }
  /*
   * 填充本地连接信息
   */
  local_addr.sin_family = AF_INET;
  local_addr.sin_port = htons(HTTP_PORT);
  local_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  memset(&(local_addr.sin_zero), '\0', 8);
  return tempSockId;              //返回取得的SOCKET
}
/**************************************
  该方法包装了send()
  通过该方法发送数据 能够全部发出
  没有遗漏
**************************************/
int sendall(int s, char *buf, int *len) {
  int total = 0;                // 已经发送字节数
  int bytesleft = *len;            // 还剩余多少字节数
  int n;
  while(total < *len) {
    n = send(s, buf+total, bytesleft, 0);  // 发送数据
    if (n == -1) { break; }
    total += n;
    bytesleft -= n;
  }
  *len = total;                // 返回实际发送出去的字节数
  return n==-1?-1:0;              // 成功发送返回0 失败-1
}
/**************************************
  主函数main()
  整个程序的入口
**************************************/
void main() {
  /*
   * 调用WSAStartup() 便于访问sockets library
   */
  WSADATA wsaData;
  if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
    fprintf(stderr, "WSAStartup failed.\n");
    exit(1);
  }
 
  /*
   * 需要用到的参数
   */
  char server[100];              //用来保存用户想要连接的服务器地址
  char command[100];              //用户命令
  char filename[100];              //用户输入的用来保存实体内容的文件名
  char buf[MAXSIZE];              //读取数据的缓存字节数组
 
  FILE * to_store;              //用来存储文件内容的文件指针
  int len = -1;
  struct sockaddr_in remote_server;      //远程服务器的连接信息
  struct hostent * host_info;          //远程服务器的地址信息
  /*
   * 主循环
   * 直到用户输入q 退出循环
   */
  while(true) {
   
    int mysocket = make_socket();      //构建本地socket
   
    cout << "Please input the web site you want to connect or 'q' to quit:" << endl;  //输出提示信息
    gets(server);              //从控制台读取用户输入
    //cout << server << endl;        //测试用 用来输出服务器名称         
   
    if (strcmp(server, "q") == 0) {      //用户输入q 退出程序
      exit(0);
    }
    /************************************
      填充远程服务器的连接信息
    *************************************/
    remote_server.sin_family = AF_INET;
    remote_server.sin_port = htons(HTTP_PORT);
    if ((host_info = gethostbyname(server)) == NULL) {          //通过服务器名得到连接信息
      cout << "Server name error or can not be reached!" << endl;    //服务器名称错误或无法连接
      cout << "*********Press any key to continue*************" << endl;//输出提示信息
      char temp[1];
      gets(temp);
      continue;
    }
    remote_server.sin_addr = *((struct in_addr *)host_info->h_addr);
    memset(&(remote_server.sin_zero), '\0', 8);
    /*************************************
      连接服务器
    *************************************/
    if (connect(mysocket, (struct sockaddr *)&remote_server,
      sizeof(struct sockaddr)) == -1) {          //连接出错
      cerr << "Connect error!" << endl;
      cout << "*********Press any key to continue*************" << endl;
      char temp[1];
      gets(temp);
      continue;
    }
   
    cout << "Now " << server << " is listening to your command!\n" << endl;    //连接成功
    /*****************************
      读取客户端命令
    ******************************/
    gets(command);
    //cout << command << endl;        //测试用 输出命令
 
    /*
     * 发送数据
     */
    len = strlen(command);
    if (sendall(mysocket, command, &len) == -1) {
      cout <<"sending error" << endl;    //发送数据出错
      continue;
    }
    cout << "The following is the header" << endl;  //输出提示信息
   
    int readed = -1;
    int i = 0;
    bool flag = false;
    readed = recv(mysocket, buf, 1, 0);             //从服务器端读取数据 readed为实际读到的
    //readed = read(mysocket, buf, 1);        //字节数 限定每次读取一个字节
    while(readed == 1) {
      /********************
        提取head信息
      ********************/
      if (i < 4) {
        if (buf[0] == '\r' || buf[0] == '\n') {    //出现两个\r\n时 i==4
          i++;
        } else {
          i = 0;
        }
        printf("%c", buf[0]);            //把http头信息打印在控制台
      /*******************
        提取文件实体
      *******************/
      } else if (flag) {                //首次进入时
        fwrite(buf, 1, 1, to_store);        //需向用户提示输入存储文件名称
      } else {
        cout << "Please input the filename to store the content file:" << endl;
        gets(filename);
        //cout << filename << endl;          //测试用 输出文件名
        to_store = fopen(filename, "w");
        flag = true;
      }
      readed = recv(mysocket, buf, 1, 0);
      //readed = read(mysocket, buf, 1);
    }
    fflush(to_store);
    shutdown(mysocket, 2);
  }
}
/*********程序结束Client.cpp***********/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值