zoukankan      html  css  js  c++  java
  • C语言实现Web客户端(转-kungstriving)

    和我的上一篇文章是一起写的,呵呵,大家给提点意见啊。
     
    :-)
     
    /*********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), '', 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. ");
      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), '', 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! " << 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] == ' ' || buf[0] == ' ') {  //出现两个 时 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***********/
  • 相关阅读:
    查看MySQL数据库表的命令介绍
    MySQL 数据库常用命令 超级实用版分享
    从cmd中进入MySQL的命令界面
    POJ-1664 放苹果
    ant常用命令
    ant来历
    ant
    ant有什么用
    ANT的安装和配置(windows)
    Experimental Educational Round: VolBIT Formulas Blitz B
  • 原文地址:https://www.cnblogs.com/sanchrist/p/3573297.html
Copyright © 2011-2022 走看看