SOCKET通過代理連線伺服器
阿新 • • 發佈:2019-02-08
代理方式包括:HTTP代理、SOCKET5代理。RFC參考文件:http://oss.org.cn/man/develop/rfc/default.htm 一、通過HTTP代理 int CProxy_TestDlg::HttpConnect(const char *proxy_ip,int proxy_port,const char *svr_ip,int svr_port) { 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 tmpBuffer[128] = {0}; ::sprintf(tmpBuffer,"CONNECT %s:%d HTTP/1.1\r\nUser-Agent: Mozilla/4.0\r\nConnection: Keep-Alive\r\n\r\n",svr_ip,svr_port); ::send(socket_,tmpBuffer,strlen(tmpBuffer),0); memset(tmpBuffer,0,128); ::recv(socket_,tmpBuffer,128,0); int mj, mi, code; ::sscanf(tmpBuffer, "HTTP/%d.%d %d", &mj, &mi, &code); if (code != 200) { ::closesocket(socket_); return 2; } ::closesocket(socket_); return 0; } HTTP代理方式測試通過。。。 二、SOCKET5代理 1、使用的結構如下: #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 CProxy_TestDlg::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,sizeof(req),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; } SOCKET5還沒有測試。。。 三、根據網址獲取該網址的IP地址 char * URL2IP(const char *url) { struct hostent * ph; struct in_addr in; memset( &in, 0x0, sizeof(in) ); // 傳遞的域名地址通過 gethostbyname 函式轉換成 HOSTENT 結構的指標 if((ph = gethostbyname(url)) == NULL) return NULL; memcpy( (char**)&in, ph->h_addr_list[0], sizeof(in) ); return ::inet_ntoa( in ); }