////////////////////////////////////////////////////////////////////
//
// ping百度 拿到一个IP 浏览器发送一个get请求
// 百度的服务器接收到了请求 返回一些东西给你
// 返回的东西就是我们想要的
//
////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <winsock2.h>
#include <string>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
/**
* 解析URL
* @param strUrl 待解析的域名
* @param strHost OUT 主机名
* @param strResource OUT
* @return false 解析失败
*/
BOOL ParseUrl(const string strUrl, string &strHost, string &strResource)
{
BOOL bRet = FALSE;
const int MAXRESOURCESIZE = 2000;
const int MINHOSTSIZE = 5;
do
{
string strHttp = "http://";
// 从strUrl中找到"http://"
const char * szPos = strstr(strUrl.c_str(), strHttp.c_str());
// 如果没有找到首"http://",说明没有http
if (NULL == szPos)
{
szPos = strUrl.c_str();
}
else
{
szPos = szPos + strHttp.length();
}
char szHost[MAXBYTE] = { 0 };
char szResource[MAXRESOURCESIZE] = { 0 }; // 标准写法:长度2000(MAXRESOURCESIZE = 2000)
sscanf_s(szPos, "%[^/]%s", szHost, MAXBYTE, szResource, MAXBYTE);
if (MINHOSTSIZE > strlen(szHost))
{
break;
}
strHost = szHost;
// 如果不等于0,说明szResource不为空
if (0 != strlen(szResource))
{
strResource = szResource;
bRet = TRUE;
}
else
{
strResource = "/";
}
} while (FALSE);
return bRet;
}
int _tmain(int argc, _TCHAR* argv[])
{
BOOL bRet = FALSE;
SOCKET socketServer = INVALID_SOCKET;
char *pszBuffer = NULL;
do
{
WSADATA wsaData;
// 初始化socket
if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
{
break;
}
if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion))
{
break;
}
// 服务端: 通过编程, 将域名转换成IP
string strUrl = "www.wmpic.me/meinv";
string strHost, strResouce;
ParseUrl(strUrl, strHost, strResouce);
printf("Host:%s \t Rosouce:%s \r\n", strHost.c_str(), strResouce.c_str());
//获取主机
HOSTENT * hServerHost = gethostbyname(strHost.c_str());
if (NULL == hServerHost)
{
WSACleanup();
break;
}
sockaddr_in addrServer = { 0 };
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(80); // 80端口
memcpy(&(addrServer.sin_addr), hServerHost->h_addr, 4);
// 创建socket
socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == socketServer)
{
closesocket(socketServer);
WSACleanup();
break;
}
// 连接socket
if (SOCKET_ERROR == connect(socketServer, (SOCKADDR*)&addrServer, sizeof(addrServer)))
{
closesocket(socketServer);
WSACleanup();
break;
}
// 发送Get请求: "GET "后面有一个空格, " HTTP/1.1" HTTP前面有个空格
// 右值为截取封包获取的
string strRequest = "GET " + strResouce + " HTTP/1.1\r\nHost:" + strHost + "\r\nConnection:Close\r\n\r\n";
if (SOCKET_ERROR == send(socketServer, strRequest.c_str(), strRequest.length(), 0))
{
closesocket(socketServer);
WSACleanup();
break;
}
// 返回的数据不可能一次性接收完毕,所以必须要用循环读取,直到recv返回0,接收完毕!
const int MAXBUFFERSIZE = 1 * 1024 * 1024;
pszBuffer = (char *)malloc(MAXBUFFERSIZE);
ZeroMemory(pszBuffer, MAXBUFFERSIZE);
int iRecvSize = 1;
int iOffset = 0;
int iReallocCount = 2;
while (0<iRecvSize)
{
iRecvSize = recv(socketServer, pszBuffer + iOffset, 100000 - iOffset, 0);
iOffset += iRecvSize;
if (MAXBUFFERSIZE - iOffset < 100)
{
pszBuffer = (char*)realloc(pszBuffer, MAXBUFFERSIZE * 2);
iReallocCount++;
}
}
cout << "szBuffer = " << pszBuffer << endl;
// 创建一个文件接收szBuffer
ofstream outPUtstream("Buffer.txt", ios::app);
outPUtstream << pszBuffer;
outPUtstream.close();
// 清理socket
if (INVALID_SOCKET != socketServer)
{
closesocket(socketServer);
WSACleanup();
}
} while (FALSE);
if (pszBuffer)
{
free(pszBuffer);
pszBuffer = NULL;
}
getchar();
return 0;
}