和我的上一篇文章是一起写的,呵呵,大家给提点意见啊。
 
:-)
 
/*********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***********/

C语言实现Web客户端(转-kungstriving)的更多相关文章

  1. python web编程-web客户端编程

    web应用也遵循客户服务器架构 浏览器就是一个基本的web客户端,她实现两个基本功能,一个是从web服务器下载文件,另一个是渲染文件 同浏览器具有类似功能以实现简单的web客户端的模块式urllib以 ...

  2. 基于gSOAP使用头文件的C语言版web service开发过程例子

    基于gSOAP使用头文件的C语言版web service开发过程例子 一服务端 1 打开VS2005,创建一个工程,命名为calcServer. 2 添加一个头文件calc.h,编辑内容如下: 1// ...

  3. 工具:SVN的Web客户端(ViewVC、SVNWebClient、sventon)和任务管理(Trac、Collaboa)

    http://www.blogjava.net/evanwhj/archive/2006/04/06/39498.aspx 在前面一篇文章中,痛诉了安装ViewVC for Subversion的种种 ...

  4. Web客户端数据存储学习笔记——Cookie

    今天对登录访问的安全以及web客户端存储做了一些大致的学习,决定在这方面加深理解,记录在博客里.第一个接触到的是Cookie... WHAT? WHY? HOW? 在学习cookie的使用时发现其名称 ...

  5. 浏览器与web客户端的HTTP交互过程

    未经许可谢绝以任何形式对本文内容进行转载! HTTP协议是常见的几种应用层协议之一,当我们用浏览器和web客户端进行交互时html页面等内容的传输都是依靠该协议完成的.值得注意的是,HTTP使用的是T ...

  6. redis web 客户端工具 redis-admin

    redis-admin是基于java的redis web客户端(redis client),以方便广大程序员使用redis为宗旨,集五种数据结构增删改查于一身. https://github.com/ ...

  7. 512MB内存VPS服务器安装宝塔WEB客户端建站 - 环境部署篇

    原本以为我们很多网友用VPS搭建网站不会用WEB面板,而采用一键包或者自己部署编译环境,但是最后发现其实目前我们使用WEB面板的还是挺多的,无论是免费还是付费的都有不少人使用.比如当初一直免费的AMH ...

  8. zookeeper的WEB客户端zkui使用

    转载自:http://blog.csdn.net/csolo/article/details/53694665 前面几篇实践说明了zookeeper如何配置和部署,如何开发,因为大多是后台操作,对于维 ...

  9. [日常] Go语言圣经-WEB服务与习题

    Go语言圣经-web服务 1.Web服务程序,标准库里的方法已经帮我们完成了大量工作 2.main函数将所有发送到/路径下的请求和handler函数关联起来,/开头的请求其实就是所有发送到当前站点上的 ...

随机推荐

  1. android 待机流程

    以下分析基于android2.2的google源码.  开机启动时,首先执行PhoneWindowManager.systemReady()(这之前的流程不分析).调用KeyguardViewMed ...

  2. Android复习指南

    基础无外乎几部分:语言(C/C++或java),操作系统,TCP/IP,数据结构与算法,再加上你所熟悉的领域.这里面其实有很多东西,各大面试宝典都有列举. 在这只列举了Android客户端所需要的和我 ...

  3. 【转】 CPU大小端

    大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中:小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中. 为什么会有大小端模式之分呢?这是因为 ...

  4. c c++怎么判断一个字符串中是否含有汉字

    c c++怎么判断一个字符串中是否含有汉字 (2013-02-05 10:44:23) 转载▼     #include  #include  int main() { char sztext[] = ...

  5. Xcode创建Object-C程序

    一. Xcode 环境安装 与 工程创建 1. 下载环境 相关资源下载 : -- IOS 相关资料下载页面 :  https://developer.apple.com/devcenter/ios/i ...

  6. SPSS数据分析—描述性统计分析

    描述性统计分析是针对数据本身而言,用统计学指标描述其特征的分析方法,这种描述看似简单,实际上却是很多高级分析的基础工作,很多高级分析方法对于数据都有一定的假设和适用条件,这些都可以通过描述性统计分析加 ...

  7. jquery插件开发基础入门

    jquery插件开发基础入门 入门 编写一个jquery插件开始于给jquery.fn加入新的功能属性,此处添加的对象属性的名称就是你的插件名称 jQuery.fn,myPlugin = functi ...

  8. Svn与Git的一些区别(转载)

    把第一条理解到位思想到位了做起来才会有的放矢,其他几条都是用的时候才能体会到 1) 最核心的区别Git是分布式的,而Svn不是分布的.能理解这点,上手会很容易,声明一点Git并不是目前唯一的分布式版本 ...

  9. chrome浏览器遇到的异常

    昨天写了一个二进制输出图片的方法,发现在chrome浏览器里面出了异常: (failed) net::ERR_INCOMPLETE_CHUNKED_ENCODING   代码是这样写的: //直接输出 ...

  10. pycharm的快捷方式

    PyCharm3.0默认快捷键(翻译的)1.编辑(Editing)Ctrl + Space 基本的代码完成(类.方法.属性)Ctrl + Alt + Space 快速导入任意类Ctrl + Shift ...