winsock编程使用Sock5代理(二)

接着上一篇博文(winsock编程使用HTTP代理),常用的代理服务方式除了HTTP以外就是Sock4和Sock5。很多软件(迅雷,QQ)都提供了各种代理服务的支持,我们来看看怎么通过sock5代理来实现网页访问吧。

Sock5代理的大致工作流程如下:

1,需要代理方向服务器发出请求信息。

2,代理方应答

3,需要代理方接到应答后发送向代理方发送目的ip和端口

4,代理方与目的连接

5,代理方将需要代理方发出的信息传到目的方,将目的方发出的信息传到需要代理方。

Sock5代理支持TCP和UDP方式,两种方式在通信上有区别,我们就来写点测试程序看看。


A:使用TCP方式代理(通信协议见源代码中step 1~step 5)

#include<WinSock2.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib")

void main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD( 1, 1 );
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		return;
	}
	if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {
		WSACleanup();
		return; 
	}
	SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

	/*
	* 初始化套接字
	*/
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr=inet_addr("192.168.194.95");
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(7070);
	
	connect(sockClient,(SOCKADDR *)&addrSrv,sizeof(SOCKADDR));

	/*
	* 通信
	*/

	//step 1:向代理服务器发送 0x05 0x01 0x00
	char proxyReq[10] = {0x05, 0x01, 0x00};
	send(sockClient,proxyReq,3,0);

	//step 2:代理服务器返回 0x05 0x00 (表示代理服务器可用)
	char recvBuffer[1000];
	memset(recvBuffer,NULL,sizeof(recvBuffer));
	recv(sockClient,recvBuffer,sizeof(recvBuffer),0);
	if(strlen(recvBuffer) == 1 && recvBuffer[0] == 0x05 && recvBuffer[1] == 0x00){

		//step 3:发送目标地址信息 0x05 0x01 0x00 0x01 220.181.111.86(www.baidu.com) 80
		char objAddr[1000] = {0x05, 0x01, 0x00, 0x01, 0xDC, 0xB5, 0x6F, 0x56, 0x00, 0x50};
		send(sockClient,objAddr,10,0);

		//step 4:接受服务器返回的自身地址和端口,连接完成
		recv(sockClient,recvBuffer,sizeof(recvBuffer),0);

		//step 5:正常的HTTP请求
		char objReq[1000] = "GET http://www.baidu.com HTTP/1.1\r\n\
Host: www.baidu.com\r\n\
User-Agent: Mozilla/5.0\r\n\
Accept: */*\r\n\
Proxy-Connection: Keep-Alive\r\n\
Connection: keep-alive\r\n\r\n";
		send(sockClient,objReq,strlen(objReq)+1,0);

		memset(recvBuffer,NULL,sizeof(recvBuffer));
		recv(sockClient,recvBuffer,sizeof(recvBuffer),0);
		printf("%s\n",recvBuffer);

	}
	closesocket(sockClient);
	WSACleanup();
}
运行程序后我们就通过代理服务器获取到了百度的首页信息

HTTP/1.1 200 OK
Date: Sat, 30 Jun 2012 06:54:49 GMT
Server: Apache
Cache-Control: max-age=86400
Expires: Sun, 01 Jul 2012 06:54:49 GMT
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: "51-4b4c7d90"
Accept-Ranges: bytes
Content-Length: 81
Connection: Keep-Alive
Content-Type: text/html

<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>
B:使用UDP方式代理(通信协议见step 1 ~ step 5,程序未通过运行,但步骤如下,怀疑是代理服务器不支持UDP通信)

#include<WinSock2.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib")

void main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD( 1, 1 );
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		return;
	}

	SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);
	SOCKET sockClientUDP=socket(AF_INET,SOCK_DGRAM,0);

	unsigned short PORT = 7070;
	/*
	* 初始化套接字
	*/
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr=inet_addr("192.168.194.95");
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(PORT);

	/*
	* 本地UDP监听
	*/
	SOCKADDR_IN localSrv;
	localSrv.sin_addr.S_un.S_addr=INADDR_ANY;
	localSrv.sin_family=AF_INET;
	localSrv.sin_port=htons(1987);
	
	bind(sockClientUDP,(SOCKADDR *)&localSrv,sizeof(SOCKADDR));

	/*
	* 通信
	*/
	//step 1:向代理服务器发送 0x05 0x01 0x00
	char proxyReq[10] = {0x05, 0x01, 0x00};
	sendto(sockClient,proxyReq,3,0,(SOCKADDR *)&addrSrv,sizeof(addrSrv));

	//step 2:代理服务器返回 0x05 0x00 (表示代理服务器可用)
	char recvBuffer[1000];
	memset(recvBuffer,NULL,sizeof(recvBuffer));
	int addrSize = sizeof(addrSrv);
	recvfrom(sockClient,recvBuffer,sizeof(recvBuffer),0,(SOCKADDR *)&addrSrv, &addrSize);//
	if(strlen(recvBuffer) == 1 && recvBuffer[0] == 0x05 && recvBuffer[1] == 0x00){

		//step 3:发送信息 0x05 0x03 0x00 0x01 0x00 0x00 0x00 0x00 1987(本地UDP端口)
		char localInfo[1000] = {0x05, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x13, 0x57};
		sendto(sockClient,localInfo,10,0,(SOCKADDR *)&addrSrv,sizeof(addrSrv));

		//step 4:服务器返回 05 00 00 01 + 服务器地址 + 端口
		memset(recvBuffer,NULL,sizeof(recvBuffer));
		recvfrom(sockClient,recvBuffer,sizeof(recvBuffer),0,(SOCKADDR *)&addrSrv, &addrSize);

		//step 5.1:发送目标地址端口信息 00 00 00 01 + 目的地址IP(4字节)+ 目的端口
		char objAddr[1000] = {0x00, 0x00, 0x00, 0x01, 0xDC, 0xB5, 0x6F, 0x56, 0x00, 0x50};
		sendto(sockClient,objAddr,10,0,(SOCKADDR *)&addrSrv,sizeof(addrSrv));

		//step 5.2:发送请求信息
		char objReq[1000] = "GET http://www.baidu.com HTTP/1.1\r\n\
Host: www.baidu.com\r\n\
User-Agent: Mozilla/5.0\r\n\
Accept: */*\r\n\
Proxy-Connection: Keep-Alive\r\n\
Connection: keep-alive\r\n\r\n";
		sendto(sockClient,objReq,strlen(objReq)+1,0,(SOCKADDR *)&addrSrv,sizeof(addrSrv));

		memset(recvBuffer,NULL,sizeof(recvBuffer));
		recvfrom(sockClientUDP,recvBuffer,sizeof(recvBuffer),0,(SOCKADDR *)&addrSrv, &addrSize);
		printf("%s\n",recvBuffer);

	}
	closesocket(sockClient);
	WSACleanup();
}

上面的测试都是最简单的代理通信,如何携带用户名密码鉴权可以去rfc手册上查查。

HTTP代理主要是代理浏览器访问网页。SOCKS代理只是简单地传递数据包,所以SOCKS代理服务器比其他类型的代理服务器速度要快得多。SOCKS4代理只支持TCP协议,SOCKS5代理则既支持TCP协议又支持UDP协议,还支持各种身份验证机制、服务器端域名解析等。

参考资料:http://www.faqs.org/rfcs/rfc1928.html 以及 http://www.cppblog.com/noflybird/archive/2009/12/26/104149.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值