首页 > 解决方案 > 如何充当客户端和服务器之间的代理?

问题描述

我正在编写一个程序,它应该充当 Web 服务器和浏览器之间的简单代理。浏览器连接到我的代理程序,我的程序连接到 Web 服务器。我的代理程序应该简单地将它从浏览器接收到的所有数据转发到 Web 服务器,反之亦然,无需以任何方式修改数据,也无需执行任何缓存。

我已经设法从网络服务器获得回复,但我如何将该回复定向到我的浏览器?还有什么方法可以将它放入某种我可以recv并且随意的无限循环中send

编辑:

我几乎明白了。我只需要知道如何连续读取套接字。收到 Http 重定向后,程序意外关闭。

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>

#define SERVER_PORT  8080
#define SA struct sockaddr
#define MAX 80

pthread_t ptid, ptidd;

#define TRUE             1
#define FALSE            0

struct sockets_struct {
    int server_sd;
    int client_sd;
    int new_sd;
}socks;

// Function designed to act as client. 
void *client_func(void *sockets)
{ 
    char   buffer[MAX];
    struct sockaddr_in servaddrr;
    struct sockets_struct *socks = (struct sockets_struct*)sockets;
    int    i, len, rc, on = 1;
    //bzero(&servaddrr, sizeof(servaddrr)); 
        
    // assign IP, PORT 
    servaddrr.sin_family = AF_INET; 
    servaddrr.sin_addr.s_addr = inet_addr("192.168.0.1"); 
    servaddrr.sin_port = htons(80);

    // connect the client socket to server socket 
    if (connect(socks->client_sd, (SA*)&servaddrr, sizeof(servaddrr)) != 0) { 
        printf(" client: connection with the server failed...\n"); 
        exit(0); 
    } 
    else
        printf(" client: connected to the remote server..\n");
        

    do {
        rc = recv(socks->client_sd, buffer, sizeof(buffer), 0);
        
        if (rc < 0) {
            if (errno != EWOULDBLOCK) {
                perror(" client: recv() failed\n");
            }
            break;
        }

        if (rc == 0) {
            printf(" client: Connection closed\n");
            break;
        }

        len = rc;
        printf(" client: %d bytes received\n", len);
        rc = send(socks->new_sd, buffer, len, 0);
        
        if (rc < 0) {
            perror(" client: send() failed");
            break;  
        }

    } while(TRUE);
}

// Function designed to act as server. 
void *server_func(void *sockets)
{
    int    len, rc, on = 1;
    int    desc_ready, end_server = FALSE, compress_array = FALSE;
    int    close_conn;
    char   buffer[80];
    struct sockaddr_in6   addr;
    int    timeout;
    struct pollfd fds[200];
    int    nfds = 1, current_size = 0, i, j;
    struct sockets_struct *socks = (struct sockets_struct*)sockets;
    
    rc = setsockopt(socks->server_sd, SOL_SOCKET, SO_REUSEADDR, 
                                            (char *)&on, sizeof(on));
    if (rc < 0) {
        perror(" server: setsockopt() failed\n");
        close(socks->server_sd);
        exit(-1);
    }

    rc = ioctl(socks->server_sd, FIONBIO, (char *)&on);
    
    if (rc < 0) {
        perror(" server: ioctl() failed\n");
        close(socks->server_sd);
        exit(-1);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin6_family      = AF_INET;
    memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
    addr.sin6_port        = htons(SERVER_PORT);
    
    rc = bind(socks->server_sd, (struct sockaddr *)&addr, sizeof(addr));
    
    if (rc < 0) {
        perror(" server: bind() failed");
        close(socks->server_sd);
        exit(-1);
    }

    rc = listen(socks->server_sd, 32);
    
    if (rc < 0) {
        perror(" server: listen() failed");
        close(socks->server_sd);
        exit(-1);
    }

    memset(fds, 0 , sizeof(fds));
    fds[0].fd = socks->server_sd;
    fds[0].events = POLLIN;
    timeout = (3 * 60 * 1000);

    do {
        printf(" server: waiting on poll()...\n");
        
        rc = poll(fds, nfds, timeout);
        if (rc < 0) {
            perror(" server: poll() failed\n");
            break;
        }

        if (rc == 0) {
            printf(" server: poll() timed out.  End program.\n");
            break;
        }

        current_size = nfds;
        for (i = 0; i < current_size; i++) {
            if (fds[i].revents == 0)
                continue;

            if (fds[i].revents != POLLIN) {
                printf(" server: Error! revents = %d\n", fds[i].revents);
                end_server = TRUE;
                break;

            }
        
            if (fds[i].fd == socks->server_sd) {
                printf("  server: Listening socket is readable\n");
                socks->new_sd = accept(socks->server_sd, NULL, NULL);
                if (socks->new_sd < 0) {
                    if (errno != EWOULDBLOCK) {
                        perror("  server: accept() failed\n");
                        end_server = TRUE;
                    }
                    break;
                }

                printf("  server: new incoming connection - %d\n", socks->new_sd);
                fds[nfds].fd = socks->new_sd;
                fds[nfds].events = POLLIN;
                nfds++;
            }
            else {
                printf("  server: Descriptor %d is readable\n", fds[i].fd);
                close_conn = FALSE;

                do {
                    rc = recv(fds[i].fd, buffer, sizeof(buffer), 0);
                    if (rc < 0) {
                        if (errno != EWOULDBLOCK) {
                            perror("  recv() failed");
                            close_conn = TRUE;
                        }
                        break;
                    }

                    if (rc == 0) {
                        printf(" server: Connection closed\n");
                        close_conn = TRUE;
                        break;
                    }

                    len = rc;
                    printf(" server: %d bytes received \n", len);
                    rc = send(socks->client_sd, buffer, len, 0);
                    
                    if (rc < 0) {
                        perror(" server: send() failed\n");
                        close_conn = TRUE;
                        break;
                    }

                } while(TRUE);

                if (close_conn) {
                    close(fds[i].fd);
                    fds[i].fd = -1;
                    compress_array = TRUE;
                }

            }  /* End of existing connection is readable */
        } /* End of loop through pollable descriptors */

    } while (end_server == FALSE); /* End of serving running. */

}   

int main (int argc, char *argv[])
{
    socks.server_sd = socket(AF_INET, SOCK_STREAM, 0);
    socks.client_sd = socket(AF_INET, SOCK_STREAM, 0);

    if (socks.server_sd == -1) { 
        printf("socket \"server_sd\" creation failed...\n"); 
        exit(0); 
    } 
    else
        printf("Socket \"server_sd\" successfully created..\n");
        
    if (socks.client_sd == -1) { 
        printf("socket \"client_sd\" creation failed...\n"); 
        exit(0); 
    } 
    else
        printf("Socket \"client_sd\" successfully created..\n");
    
    pthread_create(&ptidd, NULL, &client_func, &socks);
    pthread_create(&ptid, NULL, &server_func, &socks);
    pthread_join(ptidd, NULL);
    
    return 0;

}

标签: csocketsserver

解决方案


您可以编写一个代理来理解它所代理的数据,也可以编写一个不理解它的代理。你的问题表明你想写一个没有的。这绝对是更简单的方法。

因此,一旦设置了所有连接,您有两件事要做。您需要从一个连接读取数据并将其发送到另一个连接。您还需要从另一个连接读取数据并将其发送到第一个连接。

使用两个线程是一种简单的方法。您还可fork以为每个方向创建一个过程。但是每个人学习的第一个方法是一个selectpoll循环。您可以将“选择循环代理”插入您最喜欢的搜索引擎以查找大量示例。


推荐阅读