namespace
DEVWEB
{
struct
ACloseSkt
{
ACloseSkt(SOCKET h)
{
m_h = h;
}
~ACloseSkt()
{
if
(m_h)
closesocket(m_h);
m_h = 0;
}
SOCKET m_h;
};
struct
RequestParam
{
bool
bPost;
//是否为POST请求
const
char
* pPostData;
//为POST数据,需要自已维护内存;
unsigned
int
uiPostLen;
//为POST数据长度,主要为了兼容可以上传二进制数据,一般请求就为pPostData字符串长度
const
char
* pReferer;
//请求的引用页面,就是来源页面
const
char
* pAttachHeader;
//附加自定义头
bool
bBlock;
//true=阻塞式连接,false=异步连接,*******注意:使用异步必须设置超时时间
unsigned
int
uiTimeout;
//异步超时 单位ms
RequestParam(){
memset
(
this
,0,
sizeof
(RequestParam));
bBlock =
true
; bPost =
false
;
}
};
void
GetRealIP(string& ip, string& retip)
{
retip = ip;
unsigned
long
t = inet_addr((
char
*)(
LPCSTR
)ip.c_str());
if
(t == INADDR_NONE)
{
hostent* hostInfo = gethostbyname((
char
*)(
LPCSTR
)ip.c_str());
if
(hostInfo)
{
struct
in_addr *addr;
addr = (
struct
in_addr*)hostInfo->h_addr_list[0];
if
(addr!=NULL)
{
retip = inet_ntoa(*addr);
}
}
else
{
TRACE1(
"GetRealIP can't parse domain %s\n"
,ip.c_str());
}
}
}
//
//szURL 一个完整的URL仅HTTP,HTTPS不支持,可以包含GET参数,如index.php?username=test
//response 为请求返回的结果,包含HTTP头信息
//pRP为附加参数,完成更复杂的请求
///
bool
WebRequest(
const
char
* szURL, std::string& response, RequestParam* pRP = 0)
{
if
(!szURL )
return
false
;
SOCKET hSkt = socket(AF_INET,SOCK_STREAM,0);
if
(INVALID_SOCKET == hSkt){ OutputDebugString(
"WebRequest socket create failed!\n"
);
return
false
;}
ACloseSkt askt(hSkt);
//是否设置为异步
if
( pRP && pRP->bBlock ==
false
)
{
ULONG
nMode = 1;
ioctlsocket( hSkt,FIONBIO,&nMode);
}
string strURL(szURL),host,ip,requrl;
unsigned
int
nport = 80;
if
( stricmp(string(strURL.substr(0,7)).c_str(),
"http://"
) )
{
OutputDebugString(
"WebRequest parse url error, need http://\n"
);
return
false
;
}
else
{
//parse url;
size_t
nMH = strURL.find(
':'
,8);
size_t
nPre =strURL.find(
'/'
,8);
if
( nMH == -1 && nPre == -1)
{
host = strURL.substr(7);
requrl =
"/"
;
}
else
if
( nPre != -1){
if
( nMH != -1 && nPre > nMH){
host = strURL.substr(7,nMH-7);
nport =
atoi
( string(strURL.substr(nMH+1, nPre-1-nMH)).c_str());
}
else
{
host = strURL.substr(7,nPre-7);
}
requrl = strURL.substr(nPre);
}
else
if
(nMH != -1){
host = strURL.substr(7, nMH-7);
nport=
atoi
( string(strURL.substr(nMH+1)).c_str());
requrl =
"/"
;
}
}
GetRealIP(host,ip);
sockaddr_in addr;
addr.sin_addr.S_un.S_addr = inet_addr( ip.c_str() );
addr.sin_port = htons(nport);
addr.sin_family = AF_INET;
if
(pRP && pRP->bBlock)
{
if
(SOCKET_ERROR == connect( hSkt, (sockaddr*)&addr,
sizeof
(addr)))
{
OutputDebugString(
"WebRequest connect server failed!\n"
);
return
false
;
}
}
else
{
if
(SOCKET_ERROR == connect( hSkt, (sockaddr*)&addr,
sizeof
(addr)))
{
if
( WSAGetLastError() == 10035 )
{
//connectioning
}
else
{
OutputDebugString(
"WebRequest connect server failed!\n"
);
return
false
;
}
}
DWORD
dwTick = GetTickCount();
do
{
fd_set Set,WSet;
FD_ZERO(&Set);
FD_ZERO(&WSet);
FD_SET(hSkt,&Set);
FD_SET(hSkt,&WSet);
timeval
time
;
time
.tv_sec = 0;
time
.tv_usec = 0;
int
nS = select(0, &Set, &WSet, NULL, &
time
);
if
( nS == SOCKET_ERROR )
{
OutputDebugString(
"WebRequest connect server failed!(SELECT)\n"
);
return
false
;
}
else
if
(nS){
break
;
//connect sucess.
}
else
{
if
( (GetTickCount() - dwTick) > pRP->uiTimeout )
{
//timeout
OutputDebugString(
"WebRequest connect server timeout!(SELECT)\n"
);
return
false
;
}
}
}
while
(
true
);
}
//fill header;
string header;
bool
bSendBin =
false
;
if
(pRP)
{
header.append( pRP->bPost ?
"POST "
:
"GET "
);
header.append(requrl);
header.append(
" HTTP/1.1\r\n"
);
header.append(
"host:"
);
header.append(host);
header.append(
"\r\nUser-Agent:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)\r\n"
);
header.append(
"Content-Type:application/x-www-form-urlencoded\r\n"
);
header.append(
"Accept:text/html,application/xhtml+xml,*/*\r\nConnection:close\r\n"
);
char
szCSize[50];
sprintf
(szCSize,
"Content-Length:%d\r\n\r\n"
,pRP->uiPostLen);
header.append(szCSize);
if
(pRP->pPostData){
if
(
strlen
(pRP->pPostData) <= pRP->uiPostLen){
bSendBin =
true
;
}
else
{
header.append(pRP->pPostData);
}
}
}
else
{
header.append(
"GET "
);
header.append(requrl);
header.append(
" HTTP/1.1\r\n"
);
header.append(
"host:"
);
header.append(host);
header.append(
"\r\nUser-Agent:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)\r\n"
);
header.append(
"Content-Type:application/x-www-form-urlencoded\r\n"
);
header.append(
"Accept:text/html,application/xhtml+xml,*/*\r\nConnection:close\r\n\r\n"
);
}
size_t
headerlen = header.size();
size_t
nSendLen = 0;
const
char
* pdata = header.c_str();
DWORD
dwTick = GetTickCount();
do
{
int
n = send(hSkt, pdata + nSendLen,
int
(headerlen - nSendLen),0);
if
( n == SOCKET_ERROR ){
if
( 10035 == WSAGetLastError())
{
//wait for send.
if
(pRP && GetTickCount() - dwTick >= pRP->uiTimeout)
{
OutputDebugString(
"WebRequest send failed!\n"
);
return
false
;
}
Sleep(10);
}
else
{
OutputDebugString(
"WebRequest send failed!\n"
);
return
false
;
}
}
else
if
( n==0)
{
OutputDebugString(
"WebRequest send failed!\n"
);
return
false
;
break
;
}
else
{
dwTick = GetTickCount();
nSendLen += n;
}
}
while
(nSendLen < headerlen );
if
(bSendBin && pRP && pRP->pPostData && pRP->uiPostLen)
{
nSendLen = 0;
pdata = (
const
char
*) pRP->pPostData;
dwTick = GetTickCount();
do
{
int
n = send(hSkt, pdata + nSendLen, pRP->uiPostLen - nSendLen,0);
if
( n == SOCKET_ERROR ){
if
( 10035 == WSAGetLastError())
{
//wait for send.
if
(pRP && GetTickCount() - dwTick >= pRP->uiTimeout)
{
OutputDebugString(
"WebRequest send timeout!\n"
);
return
false
;
}
Sleep(10);
}
else
{
OutputDebugString(
"WebRequest send failed!\n"
);
return
false
;
}
}
else
if
( n==0)
{
OutputDebugString(
"WebRequest send failed!\n"
);
return
false
;
break
;
}
else
{
dwTick = GetTickCount();
nSendLen += n;
}
}
while
(nSendLen < pRP->uiPostLen );
}
//recv response
char
buf[2049];
string& request = response;
request.clear();
dwTick = GetTickCount();
do
{
int
n = recv(hSkt, buf,2048,0);
if
( n == SOCKET_ERROR )
{
if
( 10035 != WSAGetLastError() )
{
OutputDebugString(
"DevWebService recv failed!\n"
);
return
0;
break
;
}
else
{
if
(pRP && GetTickCount() - dwTick >= pRP->uiTimeout){
OutputDebugString(
"WebRequest recv timeout!\n"
);
return
false
;
}
Sleep(10);
}
}
else
if
( n == 0 ){
//host close recv finish
OutputDebugString(
"WebRequest Recv FINISHED!\n"
);
break
;
}
else
{
buf[n] =
'\0'
;
request.append(buf); dwTick = GetTickCount();
}
}
while
(
true
);
return
true
;
}
}
//test code
string rs;
char
post[80];
sprintf
(post,
"username=xj&userpassword=123456"
);
DEVWEB::RequestParam rp;
rp.bPost =
true
;
rp.pPostData = post;
rp.uiPostLen =
strlen
(post);
if
( DEVWEB::WebRequest(
"http://www.paobuke.com/wp-login.php"
, rs,&rp))
{
AfxMessageBox( rs.c_str());
}