Windows下C++實現Web客戶端

和我的上一篇文章是一起寫的,呵呵,大家給提點意見啊。
 
:-)
 
#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);
 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章