公司通过代理上网,C程序直接通过发http请求不能获取网页内容,故实现了下通过代理访问http网页的一个测试程序。
程序很简单,有几个重点
-
先通过socket直接连接代理服务器
-
向代理服务器发送HTTP的CONNECT标头,格式为CONNECT www.baidu.com:80 HTTP/1.0\r\nProxy-Authorization: Basic %s\r\n\r\n
其中%s处替换为user:passwd的base64编码
-
鉴权通过后 send请求就ok,注意此处和不用代理的区别是 GET后面的地址要http://www.baidu.com 而不能是www.baidu.com
-
这是个测试程序,目的只是说明实现过程,我测试的可以收到返回报文,也有不完善的地方,比如接收不全。
代码如下:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string>
//以下六个参数改为自己需要的即可
const char *proxyAddr="10.1.1.2";
const int proxyPort = 8080;
const char *user="domain\\name";
const char *passwd="kklklkl";
const char *desthost="www.baidu.com";
const int destport=80;
static void to64frombits(unsigned char *out, const unsigned char *in, int inlen);
int main() {
int sock_fd;
struct sockaddr_in addr;
struct hostent *hptr;
char str[32];
/* if((hptr = gethostbyname(proxyAddr)) == NULL)
{
printf(" gethostbyname error for host:%s\n", proxyAddr);
return 0;
}
*/
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("socket() fail.");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(proxyPort);
inet_aton(proxyAddr, &addr.sin_addr);
//memcpy(&addr.sin_addr.s_addr,hptr->h_addr,sizeof(addr.sin_addr.s_addr));
//printf("proxy ip=%s\n",inet_ntop(hptr->h_addrtype,hptr->h_addr,str,sizeof(str)));
if (connect(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(sock_fd);
perror("connect() fail.");
}
printf("-=-=-=-=-=-=-=We have connect the proxy ok!!!!-=-=-=-=-=-=-=\n");
char tmp[10240+1];
char authstr[10240+1];
memset(tmp,0x0,sizeof(tmp));
memset(authstr,0x0,sizeof(authstr));
sprintf(tmp,"%s:%s",user,passwd);
printf("=======%s",tmp);
to64frombits((unsigned char*)authstr,(unsigned char*)tmp,strlen(tmp));
printf("--=====%s",authstr);
snprintf(tmp,sizeof(tmp),"CONNECT %s:%d HTTP/1.0\r\nProxy-Authorization: Basic %s\r\n\r\n", desthost, destport, authstr);
send(sock_fd, tmp, strlen(tmp), 0);
printf("-=-=-=-=-=wait for recv-=-=-=-=-=\n");
memset(tmp,0x0,sizeof(tmp));
recv(sock_fd, tmp, sizeof(tmp), 0);
printf("recv=%s",tmp);
//通过代理get,此处的url一定要是全路径带上http://,否则访问不到
snprintf(tmp,sizeof(tmp),"GET %s HTTP/1.0\r\n", "http://www.baidu.com/");
strcpy(tmp+strlen(tmp),"Accept:*/*\r\n");
strcpy(tmp+strlen(tmp),"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)");
strcpy(tmp+strlen(tmp),"Accept-Language:zh-cn\r\n");
strcpy(tmp+strlen(tmp),"Connection:close\r\n\r\n");
send(sock_fd, tmp, strlen(tmp), 0);
memset(tmp,0x0,sizeof(tmp));
sleep(5);
recv(sock_fd, tmp, sizeof(tmp), 0);
printf("recv2=%s",tmp);
close(sock_fd);
return 0;
}
//base64编码函数
static void to64frombits(unsigned char *out, const unsigned char *in, int inlen)
{
const char base64digits[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for (; inlen >= 3; inlen -= 3)
{
*out++ = base64digits[in[0] >> 2];
*out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
*out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
*out++ = base64digits[in[2] & 0x3f];
in += 3;
}
if (inlen > 0)
{
unsigned char fragment;
*out++ = base64digits[in[0] >> 2];
fragment = (in[0] << 4) & 0x30;
if (inlen > 1)
fragment |= in[1] >> 4;
*out++ = base64digits[fragment];
*out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
*out++ = '=';
}
*out = '\0';
}
测试结果:
测试结果:
[@dev1 myfile]$ ./proxy_test
-=-=-=-=-=-=-=We have connect the proxy ok!!!!-=-=-=-=-=-=-=
=======test:1111132%--=====YdlsdfdiaDp6YmgyNDI3MDY1JQ==-=-=-=-=-=wait for recv-=-=-=-=-=
recv=HTTP/1.0 200 Connection established
recv2=HTTP/1.1 200 OK
Date: Wed, 06 Nov 2013 10:15:13 GMT
Server: Apache
P3P: CP=" OTI DSP COR IVA OUR IND COM "
P3P: CP=" OTI DSP COR IVA OUR IND COM "
Set-Cookie: BAIDUID=8F0C54DC13B905C0FA9EFD43B9D053C1:FG=1; expires=Thu, 06-Nov-14 10:15:13 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1
Set-Cookie: BAIDUID=8F0C54DC13B905C09E3548EFD4211EBA:FG=1; expires=Thu, 06-Nov-14 10:15:13 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1
Last-Modified: Mon, 31 Dec 2012 10:42:36 GMT
ETag: "1cdb-4d223abde3f00"
Accept-Ranges: bytes
Content-Length: 7387
Cache-Control: max-age=1
Expires: Wed, 06 Nov 2013 10:15:14 GMT
Vary: Accept-Encoding,User-Agent
Connection: Close
Content-Type: text/html
<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>百度一下,你就知道 </title><style>html{overflow-y:auto}body{font:12px arial;text-align:center;background:#fff}body,p,form,ul{margin:0;padding:0}body,form,#fm{position:relative}td{text-align:left}img{border:0}a{color:#00c}a:active{color:#f60}#u{padding:7px 10px 3px 0;text-align:right}#m{width:680px;margin:0 auto}#nv{font-size:16px;margin:0 0 4px;text-align:left;text-indent:117px}#nv a,#nv b,.btn,#lk{font-size:14px}#fm{padding-left:90px;text-align:left}#kw{width:404px;height:22px;padding:4px 7px;padding:6px 7px 2px\9;font:16px arial;background:url(http://www.baidu.com/img/i-1.0.0.png) no-repeat -304px 0;_background-attachment:fi[@dev1 myfile]$