【TCPIP】借助Winsock编写HTTP转发程序(虽然没啥用但是有代码)
我来说一下浏览器是怎么上网的。首先,网站的服务器程序开启之后,它会通过TCPIP协议监听80端口并等待连接。然后,用户通过浏览器上网,浏览器会尝试连接到服务器,连接完成以后,浏览器按照HTTP协议发送一个数据包(HTTP请求)。
服务器接收到浏览器的数据包以后,回复一个数据包给浏览器。这个数据包包括了一个HTTP头和一些其余的数据(比如网页文件、图片等)。
浏览器接收到服务器的数据包以后,显示出网页的内容。这就是浏览器的运行方式。
虽然HTTP协议我们可以自己从网上找到学习的资料,但是如果我们能自己截获这些数据包,我们就能更容易地学到它的原理。因此我写了一个转发程序。
程序运行的原理:通过TCP/IP协议监听80端口。当有浏览器连接到它的时候,它就去连接一个别的、我们指定了的网页(比如www.baidu.com)
然后把浏览器的数据包转发到网站服务器(百度)(顺带再把数据包发一份到stdout)。然后百度的服务器就会回复一个数据包,我这个转发器就截获百度的数据包并转发给浏览器(顺带再把数据包发一份到stdout)。我没有研究过HTTP协议,因此我这里就不给出HTTP协议的详细的细节了。#include<stdio.h>
#include<process.h>
#include<winsock2.h>
#define BUFSIZE 8192 //缓冲区大小
#define TARGET_WEBSITE"www.baidu.com"//要访问的网站
SOCKET g_SockToServer=INVALID_SOCKET;
SOCKET g_SockToBrowser=INVALID_SOCKET;
void Repeater1(void *p)//转发器1:接收浏览器数据,转发到服务器
{
char buffer={0};
int moredata=0;
int nRecv=0;
for(;;)//从浏览器接收数据
{
memset(buffer,0,sizeof(buffer));
nRecv=recv(g_SockToBrowser,buffer,BUFSIZE,0);//接收数据
if(WSAGetLastError()==WSAEMSGSIZE)//如果WSAGetLastError为WSAEMSGSIZE,表示数据包大小超过了缓冲区
{
moredata=1;
nRecv=BUFSIZE;
}
else
moredata=0;
printf("浏览器数据包:\n%s\n",buffer);//输出到stdout
if(send(g_SockToServer,buffer,nRecv,0)!=nRecv)//转发
{
puts("转发失败。");
break;
}
if(!moredata)
break;
}
}
void Repeater2(void *p)//转发器2:接收服务器数据,转发到浏览器
{
char buffer={0};
int moredata=0;
int nRecv=0;
for(;;)//从服务器接收数据
{
memset(buffer,0,sizeof(buffer));
nRecv=recv(g_SockToServer,buffer,BUFSIZE,0);//接收数据
if(WSAGetLastError()==WSAEMSGSIZE)
{
moredata=1;
nRecv=BUFSIZE;
}
else
moredata=0;
printf("服务器数据包:\n%s\n",buffer);//输出到stdout
if(send(g_SockToBrowser,buffer,nRecv,0)!=nRecv)
{
puts("转发失败。");
break;
}
if(!moredata)
break;
}
}
void DealWithConn(SOCKET s,void*pBuffer,int nRecv)//处理单个连接的程序
{
g_SockToBrowser=s;
g_SockToServer=socket(AF_INET,SOCK_STREAM,0);
do
{
SOCKADDR_IN sAddr={0};//连接目标
struct hostent *phostaddr;//域名解析
if(g_SockToServer==INVALID_SOCKET)
{
puts("socket失败\n");
break;
}
phostaddr=gethostbyname(TARGET_WEBSITE);//解析域名
if(!phostaddr)
{
puts("域名解析失败。");
break;
}
sAddr.sin_family=AF_INET;
sAddr.sin_port=htons(80);
sAddr.sin_addr.s_addr=*(u_long*)(phostaddr->h_addr_list);
printf("服务器IP:%u.%u.%u.%u\n",
(unsigned char)phostaddr->h_addr_list,
(unsigned char)phostaddr->h_addr_list,
(unsigned char)phostaddr->h_addr_list,
(unsigned char)phostaddr->h_addr_list);//打印IP
if(connect(g_SockToServer,(SOCKADDR*)&sAddr,sizeof(sAddr)))//连接到服务器
{
puts("连接不上目标。");
break;
}
_beginthread(Repeater1,0,NULL);//两个转发器同步执行
Repeater2(NULL);
puts("已断开连接。");
closesocket(g_SockToServer);//关闭连接
closesocket(g_SockToBrowser);
return;
}while(0);
printf("出BUG了。\nWSAGetLastError=%u\n",WSAGetLastError());
if(g_SockToServer!=INVALID_SOCKET)
closesocket(g_SockToServer);
closesocket(g_SockToBrowser);
}
int main()
{
WSADATA wsaData;
SOCKET sockListener=INVALID_SOCKET;
SOCKET sockConn=INVALID_SOCKET;
if(WSAStartup(WINSOCK_VERSION,&wsaData))//初始化Winsock库
{
printf("WSAStartup失败。\n");
return 1;
}
do
{
SOCKADDR_IN sAddr={0};
char cDataRecv={0};//多分配一个字节
int nRecv=0;
sockListener=socket(AF_INET,SOCK_STREAM,0);
if(sockListener==INVALID_SOCKET)
{
printf("socket失败\n");
break;
}
sAddr.sin_family=AF_INET;
sAddr.sin_port=htons(80);
sAddr.sin_addr.s_addr=INADDR_ANY;
if(bind(sockListener,(SOCKADDR*)&sAddr,sizeof(sAddr)))//绑定端口
{
printf("bind失败\n");
break;
}
if(listen(sockListener,SOMAXCONN))//监听
{
printf("listen失败\n");
break;
}
for(;;)
{
puts("等待建立连接。");
sockConn=accept(sockListener,NULL,NULL);//等待建立连接
if(sockConn!=INVALID_SOCKET)
{
puts("已连接。");
DealWithConn(sockConn,cDataRecv,nRecv);//处理单个连接
}
}
closesocket(sockListener);
return 0;
}while(0);
printf("遇到了某些问题。\nWSAGetLastError=%u\n",WSAGetLastError());
if(sockListener!=INVALID_SOCKET)
closesocket(sockListener);
if(sockConn!=INVALID_SOCKET)
closesocket(sockConn);
return 1;
}详细的使用方法:
方法1、运行它,然后用浏览器直接上“http://localhost/”或“http://127.0.0.1/”虽然看不到数据,但是你能捕获浏览器给出的HTTP头。
方法2、运行它之前改hosts,把目标网站域名重定向到127.0.0.1,然后运行这个程序,用浏览器上目标网站,能捕获到完整的数据。
方法3、运行它,然后在局域网的另一台电脑(或虚拟机)用浏览器访问你的电脑IP。可以看到浏览器发送的数据包。
提示:
1、开启了IIS服务或Apache服务的请事先关闭这两个服务,以免因端口冲突导致这个程序无法运行。
2、我不能保证这个程序的可移植性(因为用到了WSAGetLastError来判断缓冲区外是否还有数据)。
3、本程序由0xAA55原创。转载请指明出处。
4、完整的VC6工程以及编译生成的EXE下载:(请先回帖。回帖后就能下载。)**** Hidden Message *****
补充一下,我这里给出两个截获的HTTP头的范例。一定要注意HTTP头后面的两个空行!
以下内容是IE10发送给服务器的数据包:GET /网页文件路径 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 网站域名
DNT: 1
Connection: Keep-Alive
以下内容是谷歌浏览器(Chrome)发送给服务器的数据包:GET /网页文件路径 HTTP/1.1
Host: 网站域名
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/33.0.1750.146 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4
系统自动沙发 原来监听器是这么写的 哈哈,正看这方面的代码的了~ 学习了。good 666666666666666666 转发程序现在挺多的
页:
[1]