利用c++语言+socket实现HTTP请求,请求获得的数据效果图如下:
HTTP协议的下一层是TCP,根据HTTP协议只需要利用TCP发送下面的数据到达目标主机,目标主机就会发送相应的数据到客户端。
代码截图:
特别注意每一行末的\r\n
下面是代码实现:
//mySocket.h头文件
#include <Winsock2.h> #include <Windows.h> #include <Ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") #include <string> using namespace std; //只是对Socket中使用TCP协议的一种封装 class MySocket{ public: static int InitClient(SOCKET *sock, string ip, int port); static int CloseMySocket(SOCKET *Sock); static int SendData(SOCKET sock, const string data); static int RecvData(SOCKET sock, string &data); };
//mySocket.c源码文件
1 #include "mySocket.h" 2 3 //只是对Socket中使用TCP协议的封装 4 5 int MySocket::InitClient(SOCKET *sock, string ip, int port) 6 { 7 WSADATA wsaData;//初始化wsaData 8 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 9 { 10 return -1; 11 } 12 13 //创建套接字 14 if ((*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) 15 { 16 WSACleanup(); 17 return -1; 18 } 19 20 struct sockaddr_in serverAddr; 21 serverAddr.sin_family = AF_INET; 22 serverAddr.sin_port = htons(port); 23 serverAddr.sin_addr.s_addr = inet_addr(ip.c_str()); 24 25 if (connect(*sock, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) 26 { 27 return -1; 28 } 29 30 return 0; 31 } 32 33 int MySocket::CloseMySocket(SOCKET *sock) 34 { 35 if (closesocket(*sock) == SOCKET_ERROR) 36 { 37 WSACleanup(); 38 return -1; 39 } 40 return 0 ; 41 } 42 43 int MySocket::RecvData(SOCKET sock, string &data) 44 { 45 int bufLen = 255; 46 char buf[256]; 47 int recvLen= 0; 48 int iResult; 49 buf[bufLen] = '\0'; 50 while (true) 51 { 52 iResult = recv(sock, buf, bufLen, 0); 53 if (iResult < 0) 54 { 55 data = ""; 56 return -1; 57 } 58 59 recvLen += iResult; 60 61 if (iResult == 0) 62 { 63 return recvLen; 64 } 65 66 if (iResult == bufLen) 67 { 68 data += buf; 69 ZeroMemory(buf, bufLen); 70 continue; 71 } 72 if (iResult > 0 && iResult < bufLen) 73 { 74 data += buf; 75 return recvLen; 76 } 77 } 78 } 79 80 int MySocket::SendData(SOCKET sock, const string data) 81 { 82 int iResult = send(sock, data.c_str(), data.length(), 0); 83 if (iResult == SOCKET_ERROR) { 84 MySocket::CloseMySocket(&sock); 85 WSACleanup(); 86 return -1; 87 } 88 89 return 0; 90 }
//main函数
#include <stdio.h> #include <iostream> #include<time.h> #include "mySocket.h" using namespace std; int main() { SOCKET clientSock; string str; int iResult; if (MySocket::InitClient(&clientSock, "42.121.254.229", 80) == -1)//主机IP地址+端口号 { printf("连接失败\n"); return -1; } string head = "GET / HTTP/1.1\r\n"; head.append("Host: m.cnblogs.com\r\n");//请求的域名 head.append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"); head.append("User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36\r\n"); head.append("Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n"); head.append("Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7"); head.append("Accept-Encoding: gzip,deflate\r\n"); head.append("\r\n");//表明请求头结束了 iResult = MySocket::SendData(clientSock, head); if (iResult == -1) { printf("发送数据失败\n"); return -1; } iResult = MySocket::RecvData(clientSock, str); if (iResult == -1) { printf("接受数据失败\n"); return -1; } printf("----接受数据长度:%d----\n", iResult); printf(str.c_str()); MySocket::CloseMySocket(&clientSock); return 0; }
如果请求别的网站,有可能连返回的数据全部是乱码,那就是网站启用了gzip压缩了。
图中截图中文乱码,是因为返回的是UTF-8编码的字符,控制台默认是已GBK编码显示的。