请教:vc++完成端口实现http代理以及url过滤 本帖最后由 grewav_vip 于 2012-11-28 22:48:03 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 本帖最后由 oyljerry 于 2012-11-30 21:54:45 编辑 这个要先了解Http协议格式,协议头里带有url 可是在地址栏中输入地址,或单击某个 链接,收到好多GET或POST,那我要解哪个啊,或者都要解析吗,还有,在单击一个链接时,地址栏中显示的不是这个链接所对应的页面啊,以变量赋值的形式给出,这样链接的URL地址又怎么解析出呢??? 都要,你不是做浏览器的代理吗?浏览器连接你的代理服务器,你都得像web服务器一样处理,只是你把最终请求转到请求web服务器罢了 你可以试着处理 GET请求,因为浏览器大部分请求都是GET方式,处理好了GET,再处理其他,至于网络模型什么IOCP都不是最重要的,多线程 select也可以实现 现在很纠结的就是处理浏览器的一堆请求,至于网络模型都没什么问题。是不是用其它语言比如JAVA等什么好处理呢 浏览器连接你,你的代理服务器端会生成一个新的从浏览器到你代理的连接套接字sock1,你从HTTP头里截取出url这个不困难吧?截取好url就把url解析成IP,创建一个socket,命名为sock2,然后用sock2连接对应的服务器,然后发送从sock1读取过来的HTTP数据过去,然后在sock2上接收web服务器回来的数据,然后把数据原样从sock1发送给浏览器,这就是一个简单的代理逻辑 下面是以前我写的一个简单实验代码,只处理了GET,你可以参考下:#include <stdio.h>#include <iostream>#include <winsock2.h>#include <process.h>#include "SockInit.h"using namespace std;#define MAX_REQUESTLINE_LEN 2048 // IE请求行长度void __cdecl ServerThreadProc(void *param);int TCPsend(SOCKET s,const char*buf,int len,int flags);int TCPrecv(SOCKET s,const char*buf,int len,int flags);/************************************************ 调试环境:Visual C++6.0 SP6+platform SDK 2003 R2 程序名称:HTTP proxy Server(HttpProxySvr.cpp) 功能 :IE通过设置代理方式上网,IE所有请求均 先发到该代理服务器,代理服务器 将请求直接转发给webserver, 后从webserver读取响应后发回IE **************************************************/int main(){ USHORT uPort=9999; // 通信端口 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return 0; } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { WSACleanup( ); return 0; } SOCKET sListen = socket(AF_INET,SOCK_STREAM,0); if(sListen == INVALID_SOCKET) { printf("Failed socket(),error code :%d",WSAGetLastError()); return 0; } sockaddr_in sin; sin.sin_addr.S_un.S_addr = INADDR_ANY; sin.sin_family =AF_INET; sin.sin_port = htons(uPort); if(bind(sListen,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR) { printf("Failed bind(),error code :%d",WSAGetLastError()); closesocket(sListen); return 0; } int res =listen(sListen,200); sockaddr_in addrRemote; int len =sizeof(addrRemote); while(true) { SOCKET sNew = accept(sListen,(sockaddr*)&addrRemote,&len); if(sNew == INVALID_SOCKET) { printf("Failed accept(),error code :%d",WSAGetLastError()); return 0; } printf("收到一个IE连接(IP:%s)\n",inet_ntoa(addrRemote.sin_addr)); // 创建一个线程处理该连接 (每客户单线程模式...) _beginthread(ServerThreadProc,0,(void*)sNew); } closesocket(sListen); return 0;}void __cdecl ServerThreadProc(void *param){ SOCKET sock = (SOCKET)param; //与浏览器连接的套接口 char request[MAX_REQUESTLINE_LEN]; memset(request,0,MAX_REQUESTLINE_LEN); int res =recv(sock,request,MAX_REQUESTLINE_LEN,0); // 接收浏览器(客户端)发来的请求 if(res==0) { printf("连接断开\n"); closesocket(sock); return; } shutdown(sock,SD_RECEIVE); // 打印收到的请求 printf("header length :%d header: %s\n",res,request); // 分析请求行(分离出WebServer域名) char szAddrName[1024]={0}; //域名 int i =11; while(request[i]!='/'&&i<res) { szAddrName[i-11] = request[i]; i++; } szAddrName[i-11]='\0'; printf("WebServer address: %s\n\n",szAddrName); // 向WebServer提交请求 SOCKADDR_IN saServer; LPHOSTENT lphostent; SOCKET hsocket; int nRet; lphostent=gethostbyname(szAddrName); // 通过域名获得目标WebServer的IP if(lphostent==NULL) { printf("Failed gethostbyname(),error code:%d\n",WSAGetLastError()); return ; } hsocket = socket(AF_INET,SOCK_STREAM,0); if(hsocket==INVALID_SOCKET) { printf("Failed socket(),error code:%d\n",WSAGetLastError()); return ; } saServer.sin_family = AF_INET; saServer.sin_port = htons(80); saServer.sin_addr= *((LPIN_ADDR)*lphostent->h_addr_list); nRet = connect(hsocket,(LPSOCKADDR)&saServer,sizeof(SOCKADDR_IN)); if(nRet==SOCKET_ERROR) { printf("Failed connect(),error code:%d\n",WSAGetLastError()); closesocket(hsocket); return; } // 向webserver转发IE请求 nRet = TCPsend(hsocket,request,strlen(request),0); char dest[1000]; nRet=1; int senlen=0; while(nRet>0) { memset(dest,0,1000); nRet=recv(hsocket,dest,sizeof(dest)-1,0); // 从webserver获取数据 if(nRet==0) { printf("与webserver(%s)的连接关闭\n",szAddrName); break; } else if(nRet==SOCKET_ERROR ) { printf("Failed recv(),error code:%d\n",WSAGetLastError()); break; } dest[nRet]='\0'; senlen = TCPsend(sock,dest,nRet,0); //将数据转发给IE浏览器 if(senlen==0) { sockaddr_in sin; int len = sizeof(sin); if(getpeername(sock,(sockaddr*)&sin,&len)== SOCKET_ERROR) { printf("Failed getpeername(),error code:%d\n",WSAGetLastError()); break; } printf("与浏览器(%s)的一个连接关闭...\n",inet_ntoa(sin.sin_addr)); break; } else if(senlen==SOCKET_ERROR) { printf("Failed send(),error code:%d\n",WSAGetLastError()); break; } // printf("%s\n",dest); } // end of while(nRet>0) closesocket(sock); closesocket(hsocket);}int TCPsend(SOCKET s,const char*buf,int len,int flags){ int n=0,sendCount=0; int length =len; if(buf==NULL) return 0; while(length>0) { n=send(s,buf+sendCount,length,flags); //发送数据, if(n==SOCKET_ERROR)//网络出现异常 { printf("Failed send(),error code:%d\n",WSAGetLastError()); break; } length-=n; sendCount+=n; } return sendCount; // 返回已发送的字节数}int TCPrecv(SOCKET s,char *buf,int len,int flags){ int nRev=0,recvCount=0; int length =len; if(buf==NULL) return 0; // 循环接收数据 while(length>0) { nRev =recv(s,buf+recvCount,length,flags); if(nRev==SOCKET_ERROR)//网络出现异常 { printf("Failed recv(),error code:%d\n",WSAGetLastError()); break; } length-=nRev; recvCount+=nRev; } return recvCount; //返回接收到的字节数} 谢谢,解析URL是我理解错 了,已经搞定 了,现在有一个新问题,我是用完成端口做的,需要收到完成的HTTP请求包,比如有的请求包分两次发过 来,我需要将包的全部数据接收到,但发现包的顺序是乱的,没法重新组包啊,已经郁闷了好几天了,就一个服务线程也不行,给个思路吧。 从请求出发记录域名 然后通过认证服务器认证,如果合法让其访问web服务器 请问大家都是怎样找到编程相关工作的啊? BitBlt画地图问题 对书本不理解 也可能是我不会理解 怎样强迫waitforsingleobject函数退出 关于SQL文本的使用 谁有周公解梦?帮我解解这个梦!!100分给大家...... 谁调过《com本质论》附录B 的例程啊?我怎么调不通啊? 如何让主板扬声器发声 ------小女子想问问:想模拟实现中间件的特性,该怎么办?----- GetFieldValue取smalldatetime出现数值超出范围,跪求答案 请问如下图的目录,是创建的什么工程? 读取串口数据的线程怎么自己结束
还有,在单击一个链接时,地址栏中显示的不是这个链接所对应的页面啊,以变量赋值的形式给出,这样链接的URL地址又怎么解析出呢???
#include <iostream>
#include <winsock2.h>
#include <process.h>
#include "SockInit.h"
using namespace std;#define MAX_REQUESTLINE_LEN 2048 // IE请求行长度void __cdecl ServerThreadProc(void *param);
int TCPsend(SOCKET s,const char*buf,int len,int flags);
int TCPrecv(SOCKET s,const char*buf,int len,int flags);
/************************************************ 调试环境:Visual C++6.0 SP6+platform SDK 2003 R2 程序名称:HTTP proxy Server(HttpProxySvr.cpp) 功能 :IE通过设置代理方式上网,IE所有请求均
先发到该代理服务器,代理服务器
将请求直接转发给webserver,
后从webserver读取响应后发回IE
**************************************************/int main()
{
USHORT uPort=9999; // 通信端口
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return 0;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return 0;
}
SOCKET sListen = socket(AF_INET,SOCK_STREAM,0);
if(sListen == INVALID_SOCKET)
{
printf("Failed socket(),error code :%d",WSAGetLastError());
return 0;
} sockaddr_in sin;
sin.sin_addr.S_un.S_addr = INADDR_ANY;
sin.sin_family =AF_INET;
sin.sin_port = htons(uPort);
if(bind(sListen,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR)
{
printf("Failed bind(),error code :%d",WSAGetLastError());
closesocket(sListen);
return 0;
} int res =listen(sListen,200); sockaddr_in addrRemote;
int len =sizeof(addrRemote);
while(true)
{
SOCKET sNew = accept(sListen,(sockaddr*)&addrRemote,&len);
if(sNew == INVALID_SOCKET)
{
printf("Failed accept(),error code :%d",WSAGetLastError());
return 0;
}
printf("收到一个IE连接(IP:%s)\n",inet_ntoa(addrRemote.sin_addr)); // 创建一个线程处理该连接 (每客户单线程模式...)
_beginthread(ServerThreadProc,0,(void*)sNew);
}
closesocket(sListen); return 0;
}void __cdecl ServerThreadProc(void *param)
{
SOCKET sock = (SOCKET)param; //与浏览器连接的套接口 char request[MAX_REQUESTLINE_LEN];
memset(request,0,MAX_REQUESTLINE_LEN);
int res =recv(sock,request,MAX_REQUESTLINE_LEN,0); // 接收浏览器(客户端)发来的请求
if(res==0)
{
printf("连接断开\n");
closesocket(sock);
return;
}
shutdown(sock,SD_RECEIVE);
// 打印收到的请求
printf("header length :%d header: %s\n",res,request);
// 分析请求行(分离出WebServer域名)
char szAddrName[1024]={0}; //域名
int i =11;
while(request[i]!='/'&&i<res)
{
szAddrName[i-11] = request[i];
i++;
}
szAddrName[i-11]='\0';
printf("WebServer address: %s\n\n",szAddrName);
// 向WebServer提交请求
SOCKADDR_IN saServer;
LPHOSTENT lphostent;
SOCKET hsocket;
int nRet;
lphostent=gethostbyname(szAddrName); // 通过域名获得目标WebServer的IP
if(lphostent==NULL)
{
printf("Failed gethostbyname(),error code:%d\n",WSAGetLastError());
return ;
} hsocket = socket(AF_INET,SOCK_STREAM,0);
if(hsocket==INVALID_SOCKET)
{
printf("Failed socket(),error code:%d\n",WSAGetLastError());
return ;
}
saServer.sin_family = AF_INET;
saServer.sin_port = htons(80);
saServer.sin_addr= *((LPIN_ADDR)*lphostent->h_addr_list);
nRet = connect(hsocket,(LPSOCKADDR)&saServer,sizeof(SOCKADDR_IN));
if(nRet==SOCKET_ERROR)
{
printf("Failed connect(),error code:%d\n",WSAGetLastError());
closesocket(hsocket);
return;
}
// 向webserver转发IE请求
nRet = TCPsend(hsocket,request,strlen(request),0);
char dest[1000];
nRet=1;
int senlen=0;
while(nRet>0)
{
memset(dest,0,1000);
nRet=recv(hsocket,dest,sizeof(dest)-1,0); // 从webserver获取数据
if(nRet==0)
{
printf("与webserver(%s)的连接关闭\n",szAddrName);
break;
}
else if(nRet==SOCKET_ERROR )
{
printf("Failed recv(),error code:%d\n",WSAGetLastError());
break;
}
dest[nRet]='\0'; senlen = TCPsend(sock,dest,nRet,0); //将数据转发给IE浏览器
if(senlen==0)
{
sockaddr_in sin;
int len = sizeof(sin);
if(getpeername(sock,(sockaddr*)&sin,&len)== SOCKET_ERROR)
{
printf("Failed getpeername(),error code:%d\n",WSAGetLastError());
break;
}
printf("与浏览器(%s)的一个连接关闭...\n",inet_ntoa(sin.sin_addr));
break;
}
else if(senlen==SOCKET_ERROR)
{
printf("Failed send(),error code:%d\n",WSAGetLastError());
break;
} // printf("%s\n",dest); } // end of while(nRet>0)
closesocket(sock);
closesocket(hsocket);}int TCPsend(SOCKET s,const char*buf,int len,int flags)
{
int n=0,sendCount=0;
int length =len;
if(buf==NULL)
return 0;
while(length>0)
{
n=send(s,buf+sendCount,length,flags); //发送数据,
if(n==SOCKET_ERROR)//网络出现异常
{
printf("Failed send(),error code:%d\n",WSAGetLastError());
break;
}
length-=n;
sendCount+=n;
} return sendCount; // 返回已发送的字节数
}int TCPrecv(SOCKET s,char *buf,int len,int flags)
{
int nRev=0,recvCount=0;
int length =len; if(buf==NULL)
return 0; // 循环接收数据
while(length>0)
{
nRev =recv(s,buf+recvCount,length,flags);
if(nRev==SOCKET_ERROR)//网络出现异常
{
printf("Failed recv(),error code:%d\n",WSAGetLastError());
break;
}
length-=nRev;
recvCount+=nRev;
} return recvCount; //返回接收到的字节数
}