如何建立socket5代理服务器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何建立socket5代理服务器相关的知识,希望对你有一定的参考价值。

参考技术A   (1)设置用户验证和记账功能,可按用户进行记账,没有登记的用户无权通过代理服务器访问Internet网。并对用户的访问时间、访问地点、信息流量进行统计。
  (2)对用户进行分级管理,设置不同用户的访问权限,对外界或内部的Internet地址进行过滤,设置不同的访问权限。
  
  (3)增加缓冲器(Cache),提高访问速度,对经常访问的地址创建缓冲区,大大提高热门站点的访问效率。通常代理服务器都设置一个较大的硬盘缓冲区(可能高达几个GB或更大),当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时,则直接由缓冲区中取出信息,传给用户,以提高访问速度。本回答被提问者和网友采纳

在使用C语言的socket编程中,如何设置服务器接受客户端建立连接的时间限制?

【中文标题】在使用C语言的socket编程中,如何设置服务器接受客户端建立连接的时间限制?【英文标题】:In socket programming using C language, how to set time limit on server for accepting client to establish connection? 【发布时间】:2021-01-23 04:05:10 【问题描述】:

我正在开发一个涉及 1 个客户端和 1 个服务器的应用程序。

我希望服务器只侦听 5 秒钟的连接。如果客户端未尝试建立连接,则服务器应停止侦听并返回错误消息。如果客户端尝试建立连接,那么服务器应该接受连接。

如果客户端没有尝试建立连接,服务器会一直监听。我希望服务器只监听 5 秒,如何实现?

这是服务器端的输出 - 服务器一直在等待客户端:

void reception()
    int sockfd, connfd, len; 
    struct sockaddr_in servaddr, cli; 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd == -1)  
        printf("socket creation failed...\n"); 
        exit(0); 
     
    else
        printf("Socket successfully created..\n"); 
    bzero(&servaddr, sizeof(servaddr)); 

    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(PORT); 

    if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0)  
        printf("socket bind failed...\n"); 
        exit(0); 
     
    else
        printf("Socket successfully binded..\n"); 

    if ((listen(sockfd, 5)) != 0)  
        printf("Listen failed...\n"); 
        exit(0); 
     
    else
        printf("Server listening..\n"); 
    len = sizeof(cli); 

    connfd = accept(sockfd, (SA*)&cli, &len); 

    /*
        Some function should be added at this point to 
        stop the server from listening after 5 seconds

    */
    
    if (connfd < 0)  
        printf("server acccept failed...\n"); 
        exit(0); 
     
    else
        printf("server acccept the client...\n"); 

    receive(connfd); 
    close(sockfd); 



【问题讨论】:

【参考方案1】:

您在阻塞模式下使用侦听套接字,因此accept() 将阻塞调用线程,直到客户端连接。要使用超时,请先调用 select()(e)poll() 以等待侦听套接字进入可读状态,指示连接处于挂起状态,然后再调用 accept()

例如:

...

fd_set rds;
FD_ZERO(&rds);
FD_SET(sockfd, &rds);

struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;

int res;
if ((res = select(sockfd+1, &rds, NULL, NULL, &timeout)) <= 0)

    if (res < 0)
        printf("select failed...\n"); 
    else
        printf("Time out...\n"); 
    exit(0); 


connfd = accept(sockfd, (SA*)&cli, &len); 
...
...

struct pollfd pfd;
pfd.fd = sockfd;
pfd.events = POLLIN;
pfd.revents = 0;

int res;
if ((res = poll(&pfd, 1, 5000)) <= 0)

    if (res < 0)
        printf("poll failed...\n"); 
    else
        printf("Time out...\n"); 
    exit(0); 


connfd = accept(sockfd, (SA*)&cli, &len); 
...
int epfd = epoll_create(1);
if (epfd < 0)

    printf("epoll_create failed...\n"); 
    exit(0);


struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = sockfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev) < 0)

    printf("epoll_ctl failed...\n"); 
    exit(0);


struct epoll_event event;
int res;
if ((res = epoll_wait(epfd, &event, 1, 5000)) <= 0)

    if (res < 0)
        printf("epoll_ctl failed...\n"); 
    else
        printf("Time out...\n"); 
    exit(0);


close(epfd);

connfd = accept(sockfd, (SA*)&cli, &len); 
...

无论哪种方式,请注意这些场景会产生非常小的竞争条件。如果客户端在调用accept() 之前连接然后断开accept() 可能阻塞等待新的挂起连接,或者它可能返回一个在后续 I/O 调用中失败的有效文件描述符。没有任何一种方式可以保证。

要解决竞争条件,您可以:

将监听套接字置于非阻塞模式。如果select() 报告监听套接字有一个挂起的连接,但accept() 无法立即接受,那么您可以采取相应的行动。

在阻塞模式下在侦听套接字上使用accept(),就像您最初一样,但使用alert() 来安排accept() 如果它在5 秒内没有退出则被中断。示例见this answer。

【讨论】:

以上是关于如何建立socket5代理服务器的主要内容,如果未能解决你的问题,请参考以下文章

C# HttpWebRequest 如何实现SOCKET5代理

git设置代理

使用java实现的socket代理(支持socket4和socket5)

ie怎么设置socket代理

怎么隐藏自己电脑上的IP地址

Ubuntu 终端使用ss代理