Windows下C++实现Web客户端

本文介绍了一个简单的HTTP客户端程序实现过程,使用C++语言并结合Winsock库完成与服务器的连接及数据交互。程序允许用户输入目标网站地址进行连接,并接收服务器响应的数据,支持将获取的内容保存到本地文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

和我的上一篇文章是一起写的,呵呵,大家给提点意见啊。
 
:-)
 
#include <winsock.h>
#include <iostream>
#define HTTP_PORT 80       //HTTP连接的默认端口号
#define MAXSIZE 256        //自定义的每次传输数据的最大数量
using namespace std;

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
}

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
}

void main() {
 
 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;     //远程服务器的地址信息
 
 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) {
   
   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);
 }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值