C SOCKS5代理接口没有从代理服务器接收任何内容。

时间:2014-11-20 02:54:48

标签: c sockets proxy tor socks

我使用C套接字实现了一个简单的SOCKS5代理RFC 1928实现,以便与在localhost:9050上运行的tor守护进程进行通信。它编译并正常工作,但它不会阻塞,因为它不会recv()任何东西。

代码如下:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int main(int argc, char** argv) {

    struct addrinfo hints, *res;
    int sockfd;
    memset(&hints,0,sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo("localhost","9050",&hints,&res);

    sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
    int connected = connect(sockfd,res->ai_addr,res->ai_addrlen);
    if (connected == -1) {
        perror("Error");
    }
    char buffer[256];
    char msginit[256];
    msginit[0] = '\5'; //Protocol number
    msginit[1] = '\2'; //# of authentication methods
    msginit[2] = '\0'; //no authentication 
    msginit[3] = '\2'; //user+pass auth

    //get dest
    memset(&hints,0,sizeof hints);
    memset(res,0,sizeof *res);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo("duckduckgo.com","80",&hints,&res);
    struct sockaddr_in *ip = (struct sockaddr_in *)res->ai_addr;
    uint32_t* addr=&(ip->sin_addr.s_addr);

    //copy dest to request
    memcpy (msginit+4,addr,sizeof (uint32_t)); 

    send(sockfd, (void *)msginit, (size_t)strlen(msginit),0);
    printf("Sent.\n");
    recv(sockfd,buffer,256,0); //This is where it gets stuck!
    printf("%s\n",buffer);
}

1 个答案:

答案 0 :(得分:0)

我的回答如下。进一步了解它,有一个握手过程,还有更多需要发生的事情。我会在接下来的几天回复我提出的问题。 (这也是我自己也在努力的事情)


与代码一样,您只会从响应中提取前256个字节。

有几种选择,具体取决于您希望数据的速度。最后,您可能看不到太多(如果有的话)差异。但你确实有选择。

1 - 放置recv调用立即开始一个循环,直到你有完整的响应。如果您需要尽快获得数据,我会建议使用此方法。确保在那里有一个睡眠/睡眠呼叫,或者你会很难在CPU上旋转。

它可能看起来像这样:

send(sockfd, (void *)msginit, (size_t)strlen(msginit),0);
printf("Sent.\n");
while (len_recv = recv(sockfd,buffer,256,0)){
    if (len_recv > 0){
        // there was an error. handle it here.
    } 
    // copy your buffer if you need to, otherwise...
    printf("%s",buffer);
    usleep(10000);
}

2 - 使用MSG_WAITALL选项,该选项将阻止接收呼叫,直到它从请求的服务器收到整个消息,然后从套接字中提取所有数据。这就是我每天为数百万个套接字请求做的事情。

len_recv = recv(sockfd,buffer,256,MSG_WAITALL);
if (len_recv > 0){
    // start a while loop like above
    // copy the buffer if you need to, or...
    printf("%s",buffer);
}

就个人而言,在我运行速度非常快的代码中(每天有数亿个请求),我使用MSG_WAITALL选项和一个足够大的缓冲区来满足我的需求,这样我就不会循环我的recv调用。这可能不适合你,但好处是你不必考虑循环中额外的cpu周期。如果您正在执行大量请求或需要解析数据而不是仅仅转储输出,这将非常方便。

如果您可以向我提供有关如何使用此功能的更多详细信息,我可以将更完整和经过测试的代码示例放在一起,并提供更直接的建议。