[转]利用Winsock实现HTTP的GET请求

网络爬虫需要从指定的URL通过HTTP协议来获得HTML文件信息,以此从一个URL爬到另一个URL。在Windows平台上,这往往通过WinINet接口实现。
  但是,如果对HTTP协议熟悉的话,也可以通过Winsock接口实现。代码如下。

  1 #pragma warning (disable:4996)
  2 
  3  #define DEFAULT_URL "http: // www.google.com"
  4 
  5 BOOL WinsockStartup(BYTE highVer, BYTE lowVer)
  6 {
  7     WSADATA wsaData;
  8      return WSAStartup(MAKEWORD(highVer, lowVer), &wsaData) == 0;
  9 }
 10 
 11  int SendData(SOCKET s,  char * data)
 12 {
 13      return send(s, data, strlen(data), 0);
 14 }
 15 
 16  void ParseTheURL( char * pszURL,  char * pszHostName)
 17 {
 18      char * p, * pHostStart;
 19 
 20     p = strstr(pszURL, "http://");
 21      if (p && p == pszURL)
 22     {
 23         pHostStart = pszURL + 7;
 24     }
 25      else
 26     {
 27         pHostStart = pszURL;
 28     }
 29     p = strchr(pHostStart, '/');
 30      if (p)
 31     {
 32         memcpy(pszHostName, pHostStart, p - pHostStart);
 33     }
 34      else
 35     {
 36         memcpy(pszHostName, pHostStart, strlen(pHostStart));
 37     }
 38 }
 39 
 40  int _tmain()
 41 {
 42      int iRet = 0;
 43     DWORD dwError = 0;
 44     BOOL bOk = FALSE;
 45 
 46      char szURL[256] = { 0 };                 //  主机文件,即URL
 47       char szHostName[256] = { 0 };             //  主机名
 48       char szPortName[] = "80";                 //  端口号
 49 
 50      if (!WinsockStartup(2, 2))
 51     {
 52         _tcprintf(TEXT("初始化Windows Sockets失败!"));
 53         cin.getline(szURL, 255);
 54          return -1;
 55     }
 56 
 57     addrinfo aiHints = { 0 };
 58     addrinfo * aiList;
 59 
 60     aiHints.ai_family = AF_INET;
 61     aiHints.ai_socktype = SOCK_STREAM;
 62     aiHints.ai_protocol = IPPROTO_TCP;
 63 
 64     cout<<"输入URL:";
 65     cin.getline(szURL, 255);
 66 
 67      if (strcmp(szURL, "") == 0)
 68     {
 69         strcpy(szURL, DEFAULT_URL);
 70         cout<<DEFAULT_URL<<endl;
 71     }
 72 
 73     ParseTheURL(szURL, szHostName);
 74 
 75      if (getaddrinfo(szHostName, szPortName, NULL, &aiList) != 0)
 76     {
 77         _tcprintf_s(TEXT("getaddrinfo失败:%d"), WSAGetLastError());
 78         WSACleanup();
 79         cin.getline(szURL, 255);
 80          return -1;
 81     }
 82 
 83     SOCKET s;
 84      for (addrinfo * aiPtr = aiList; aiPtr != NULL; aiPtr = aiPtr->ai_next)
 85     {
 86         s = socket(aiList->ai_family, aiList->ai_socktype, aiList->ai_protocol);
 87          if (s == INVALID_SOCKET)
 88         {
 89             _tcprintf_s(TEXT("socket创建失败:%d"), WSAGetLastError());
 90              continue;
 91         }
 92 
 93          if (connect(s, aiPtr->ai_addr, aiPtr->ai_addrlen) == SOCKET_ERROR)
 94         {
 95             closesocket(s);
 96             s = INVALID_SOCKET;
 97             _tcprintf_s(TEXT("connect失败:%d"), WSAGetLastError());
 98              continue;
 99         }
100          break;
101     }
102 
103     freeaddrinfo(aiList);
104 
105      if (s == INVALID_SOCKET)
106     {
107         WSACleanup();
108         cin.getline(szURL, 255);
109          return -1;
110     }
111 
112      char requestData[512] = { 0 };
113     sprintf(requestData, "GET %s HTTP/1.1\r\n", szURL);
114     SendData(s, requestData);
115      // SendData(s, "GET / HTTP/1.1\r\n");
116      sprintf(requestData, "Host:%s\r\n", szHostName);
117     SendData(s, requestData);
118     SendData(s, "Accept: */*\r\n");
119     SendData(s, "User-Agent: Mozilla/4.0(compatible; MSIE 5.00; Windows NT)\r\n");
120     SendData(s, "Connection:Close\r\n");
121      // SendData(s, "Connection:Keep-Alive\r\n");
122      SendData(s, "\r\n");
123     SendData(s, "\r\n"); // 最后要加空行
124 
125     BOOL done = FALSE;
126      char buffer[1024] = { 0 };
127      int l, chars = 0;
128 
129      //  打印http响应的头部
130       while (!done)
131     {
132         l = recv(s, buffer, 1, 0);
133          if (l <= 0)
134             done = TRUE;
135          switch(*buffer)
136         {
137          case '\r':
138              break;
139          case '\n':
140              if(chars == 0)
141                 done = TRUE;
142             chars = 0;             //  表示另起一行
143               break;
144          default:
145             ++chars;
146              break;
147         }
148         printf("%c",*buffer);
149     }
150 
151      //  接收正文部分
152       int sum = 0;
153      do
154     {
155         l = recv(s, buffer,  sizeof (buffer) - 1, 0);
156          if( l <= 0 )
157              break;
158         sum += l;
159         *(buffer + l) = 0;
160         printf(buffer);
161     }  while( l > 0 );
162 
163      // 这里输出正文部分大小,发现其实和响应消息头部的Content-length大小是一样的
164       // 这样就可以检查是否接受完毕
165      printf("\n\n大小 = %d字节\n",sum);
166 
167     WSACleanup();
168 
169     cin.getline(szURL, 255);
170      return 0;
171 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值