#pragma pack(push,1)
//请求认证方式
typedef struct tagSocket5_Requst
{
char Ver; //版本号:05
char NMethods;
char Methods[255];
}Socket5_Request,*LPSocket5_Request;
//认证方式应答
typedef struct tagSocket5_Response
{
char Ver;
char Method;//X'00'不需要认证;X'01'GSSAPI;X'02用户名/密码;X'03' -- X'7F'由IANA分配;X'80' -- X'FE'为私人方法所保留的;X'FF'没有可以接受的方法
}Socket5_Response,*LPSocket5_Response;
//认证请求
typedef struct tagSocket5_Auth_Request
{
char Ver; //1
char Ulen;
char Name[255];
char PLen;
char Pass[255];
}Socket5_Auth_Request,*LPSocket5_Auth_Request;
typedef struct tagSocket5_Auth_Response
{
char Ver;
char Status;
}Socket5_Auth_Response,*LPSocket5_Auth_Response;
//连接请求
typedef struct tagSocket5_Connect_Request
{
char Ver;
char Cmd;//CONNECT:X'01';BIND:X'02';UDP ASSOCIATE:X'03'
char Rsv;//保留,填0
char Atyp;// 后面的地址类型,IPV4:X'01';域名:X'03';IPV6:X'04',暂时只支持IPV4
unsigned long DestAddr;//IPV4是4个字节,IPV6是6个字节;基于域名的地址,地址字段中的第一字节是以字节为单位的该域名的长度,没有结尾的NUL字
unsigned short DestPort;
}Sokcet5_Connect_Request,*LPSocket5_Connect_Request;
//连接应答
typedef struct tagSokcet5_Connect_Response
{
char Ver;
char Rep;
char Rsv;
char Atyp;
unsigned long DestAddr;
unsigned short DestPort;
}Socket5_Connect_Response,*LPSocket5_Connect_Response;
#pragma pack(pop)
2、函数定义:
int Socket5Connect(const char *proxy_ip,int proxy_port,const char *user,const char *passwd,const char *svr_ip,int svr_port)
{
//首先连接SOCKET5代理服务器
SOCKET socket_ = ::socket(AF_INET,SOCK_STREAM,0);
sockaddr_in sa;
sa.sin_addr.s_addr = inet_addr(proxy_ip);
sa.sin_port = htons(proxy_port);
sa.sin_family = AF_INET;
int error_code = ::connect(socket_,(SOCKADDR*)&sa,sizeof(sa));
if(error_code == SOCKET_ERROR)
{
::closesocket(socket_);
return 1;
}
char buffer[128] = {0};
int len = 0;
//发送认证发送请求Socket5_Request/Socket5_Response
Socket5_Request req;
Socket5_Response rep;
req.Ver = 0x05;
req.NMethods = 2;
req.Methods[0] = 0;
req.Methods[1] = 2;
if((len = ::send(socket_,(char*)&req,4,0)) <=0)
{
::closesocket(socket_);
return 4;
}
if((len = ::recv(socket_,(char*)&rep,sizeof(rep),0)) <=0)
{
::closesocket(socket_);
return 4;
}
if(rep.Ver != 0x05)
{
::closesocket(socket_);
return 5;
}
if(rep.Method != 0x00 && rep.Method != 0x02)
{
::closesocket(socket_);
return 6;
}
if(rep.Method == 0x02)
{//需要用户名、密码验证
//进行认证Socket5_Auth_Request/Socket5_Auth_Response
Socket5_Auth_Request auth_req;
Socket5_Auth_Response auth_rep;
memset(&auth_req,0,sizeof(Socket5_Auth_Request));
memset(&auth_rep,0,sizeof(Socket5_Auth_Response));
auth_req.Ver = 1;//?
auth_req.Ulen = strlen(user);
strcpy(auth_req.Name,user);
auth_req.PLen = strlen(passwd);
strcpy(auth_req.Pass,passwd);
if((len = ::send(socket_,(char*)&auth_req,sizeof(auth_req),0)) <=0)
{
::closesocket(socket_);
return 4;
}
if((len = ::recv(socket_,(char*)&auth_rep,sizeof(auth_rep),0)) <=0)
{
::closesocket(socket_);
return 4;
}
if(auth_rep.Status != 0)
{
::closesocket(socket_);
return 7;
}
}
//发送连接请求Sokcet5_Connect_Request/Socket5_Connect_Response
Sokcet5_Connect_Request conn_req;
Socket5_Connect_Response conn_rep;
memset(&conn_req,0,sizeof(Sokcet5_Connect_Request));
memset(&conn_rep,0,sizeof(Socket5_Connect_Response));
conn_req.Ver = 0x05;
conn_req.Cmd = 0x01;//
conn_req.Atyp = 0x01;
conn_req.DestAddr = inet_addr(svr_ip);
conn_req.DestPort = htons(svr_port);
if((len = ::send(socket_,(char*)&conn_req,sizeof(conn_req),0)) <=0)
{
::closesocket(socket_);
return 4;
}
if((len = ::recv(socket_,(char*)&conn_rep,sizeof(conn_rep),0)) <=0)
{
::closesocket(socket_);
return 4;
}
if(conn_rep.Rep != 0)
{
::closesocket(socket_);
return 8;
}
//连接成功
::closesocket(socket_);
return 0;
}