C中的套接字编程 - 让浏览器删除已发送的消息

时间:2014-10-22 23:17:33

标签: c sockets tcp

我正在创建一个简单的代理来过滤网站,这是我网络课程中的一项任务,所以不要介意过滤后的单词;)

它的工作可以说是好的,我唯一的问题是,当用户试图在浏览器中访问的页面包含“坏词”时。由于对所请求的网络服务器的响应来自包,因此在实际包含错误单词的数据包到达时,第一个(大多数时候标题)已经被发送到浏览器。 当代理检测到错误的单词时,它应该重定向到我老师给出的网站。问题是,新网站的响应当然有自己的标题,但由于浏览器之前已有一个标题,他将这个新标题视为简单文本,并将其显示为网页。

有没有更好的重定向方法,这可以解决这个问题,还是有另一种方法,比如让浏览器删除最后收到的消息?

哦,这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>

#define BACKLOG 10   // how many pending connections queue will hold
#define MAXDATASIZE 100 // max number of bytes we can get at once
#define PORT "1025"


// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}



int main(void)
{
    int sock_fd, new_fd, web_fd, re_fd;  
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage their_addr;
    socklen_t sin_size;
    int yes=1;
    char s[INET6_ADDRSTRLEN];
    int rv, bytes_recv, bytes_sent, total_bytes, i = 0, x, showget = 0, showpart = 0, counter = 0;

    char getter[1000], link[1000], url[500], buffer[4096], *redirect;
    bool bad_content = 0;

    printf("Starting server.\n");
    //printf("Give port: \n");
    //scanf("%s", &port);
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0)
    {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }


    for(p = servinfo; p != NULL; p = p->ai_next)
    {
        if ((sock_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
        {
            perror("server: socket");
            continue;
        }

        if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
        {
            perror("setsockopt");
            exit(1);
        }

        if (bind(sock_fd, p->ai_addr, p->ai_addrlen) == -1)
        {
            close(sock_fd);
            perror("server: bind");
            continue;
        }

        break;
    }

    if (p == NULL)
    {
        fprintf(stderr, "server: failed to bind\n");
        return 2;
    }

    freeaddrinfo(servinfo); 

    if (listen(sock_fd, BACKLOG) == -1)
    {
        perror("listen");
        exit(1);
    }


    printf("server: waiting for connections...\n");

    while(1)
    { 
        sin_size = sizeof their_addr;
        new_fd = accept(sock_fd, (struct sockaddr *)&their_addr, &sin_size);

        if (new_fd == -1)
        {
            perror("accept");
            continue;
        }

        inet_ntop ( their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr),
                    s, sizeof s);

        printf("\n--------------------------------------------\n"
               "server: got connection from %s\n", s);


//-----------RECEIVING GET FROM BROWSER-----------------------------------------------

        printf("server: Receiving GET from browser ...  ");
        memset(&getter, 0, sizeof getter);     
        if (!bad_content)
        {
            read(new_fd, getter, 4096);
        }
        else
        {
            while (1)
            {   
                getter [i] = redirect [i];
                ++i;
                if (redirect [i] == 0)
                {
                    break;
                }
            }
        }

        printf("Done\n");

        /*if (strstr(getter, "favicon") != NULL)
        {
            continue;
        }*/ 

        //showget = 1;

        if (showget)
        {
            printf( "----------GET------------\n"
                    "%s\n"
                    "-------------------------\n", getter);
        }

        memset(&url, 0, sizeof url);

//-----------EXTRACTING HOST----------------------------------------------------------

        printf("server: Extracting host address ...  ");
        i = 0;
        while (1)
        {   
            if (!(getter[i] == '/' && getter[i+1] == '/'))
            {
                i++;
            }
            else
            {
                i++;i++;
                break;
            }
        }       

        x=i;

        while (1)
        {   
            url [i-x] = getter [i];
            ++i;
            if (getter [i] == ' ' || getter [i] == ':' || 
                getter [i] == '/')
            {
                break;
            }
        }

        char host[strlen(url)];
        memset (&host, 0, sizeof host );
        i = 0;
        while (1)
        {   
            host [i] = url [i];
            ++i;
            if (url [i] == 0 || url [i] == '/' || url [i] == ' ')
            {
                break;
            }    
        }
        printf("Done\n");
//-----------CLIENT------------------------------------------------------------------

        printf("Starting client.\n");


        printf("client: Connecting to: \"%s\" ...  ", host);

//-----------CONNECTING TO WEB-------------------------------------------------------

        if ((rv = getaddrinfo( host, "80", &hints, &servinfo)) != 0)
        {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));

        }
        p=servinfo;
        for(p; p != NULL; p = p->ai_next)
        {
            if ((web_fd = socket(p->ai_family, p->ai_socktype,
                    p->ai_protocol)) == -1)
            {
                perror("client: socket");
                continue;
            }

            if (connect(web_fd, p->ai_addr, p->ai_addrlen) == -1)
            {
                close(web_fd);
                perror("client: connect");
                continue;
            }

            break;
        }

        if (p == NULL)
        {
            fprintf(stderr, "client: failed to connect, try again!\n");
            continue;
        }

        memset(&s, 0, sizeof s );
        inet_ntop ( p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
                    s, sizeof s);
        printf("Done\n");

        freeaddrinfo(servinfo);
        //fcntl(web_fd, F_SETFL, O_NONBLOCK);

//-----------SENDING GET REQUEST-----------------------------------------------------

        printf("client: Forwarding GET to \"%s\" ...  ", s);
        i = 0;
        while (1)
        {
            link[i] = getter[i];
            if ( link [i] == 13)
            {
                counter++;
            }
            else if (counter == 2)
            {
                break;
            }
            i++;
        }

        if ((bytes_sent = send(web_fd, link, strlen(link), 0)) < strlen(link))
        {
            fprintf(stderr, "client: failed to send entire GET...\n");  
            return 0;
        }
        printf("Done\n");
        memset(&buffer, 0, sizeof buffer );

//-----------RECEIVING RESPONSE-------------------------------------------------------

        printf("client: Receiving response.\n");
        total_bytes = 0;        


        while (1)
        {
            bytes_sent = 0; bytes_recv = 0;
            memset(&buffer, 0, sizeof buffer );
            if ((bytes_recv = recv(web_fd, buffer, 4096, 0)) == 0)         //receive part
            {
                break;
            }

            printf("Received part (%d bytes)\n", bytes_recv);

            if( (strstr(buffer, "SpongeBob") != NULL) ||            //checking for bad words
                 strstr(buffer, "Britney Spears") != NULL ||
                 strstr(buffer, "Paris Hilton") != NULL ||
                 strstr(buffer, "Norrk\224ping") != NULL )
            {
                printf("Bad site! Redirecting ...\n");

                //-----------CONNECTING TO WEB-------------------------------------------------------

                printf("client: Connecting to: \"www.ida.liu.se\" ...  ");

                if ((rv = getaddrinfo( "www.ida.liu.se", "80", &hints, &servinfo)) != 0)
                {
                    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));

                }
                p=servinfo;
                for(p; p != NULL; p = p->ai_next)
                {
                    if ((re_fd = socket(p->ai_family, p->ai_socktype,
                            p->ai_protocol)) == -1)
                    {
                        perror("client: socket");
                        continue;
                    }

                    if (connect(re_fd, p->ai_addr, p->ai_addrlen) == -1)
                    {
                        close(re_fd);
                        perror("client: connect");
                        continue;
                    }

                    break;
                }

                if (p == NULL)
                {
                    fprintf(stderr, "client: failed to connect, try again!\n");
                    continue;
                }

                memset(&s, 0, sizeof s );
                inet_ntop ( p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
                            s, sizeof s);
                printf("Done\n");

                freeaddrinfo(servinfo);
                //fcntl(web_fd, F_SETFL, O_NONBLOCK);

                //-----------SENDING GET REQUEST-----------------------------------------------------

                printf("client: Forwarding GET to \"%s\" ...  ", s);

                redirect =  "GET /~TDTS04/labs/2011/ass2/error2.html\r\n"
                            "Host: www.ida.liu.se\r\n\r\n";

                if ((bytes_sent = send(re_fd, redirect, strlen(redirect), 0)) < strlen(redirect))
                {
                    fprintf(stderr, "client: failed to send entire GET...\n");  
                    return 0;
                }
                printf("Done\n");
                memset(&buffer, 0, sizeof buffer );

                //-----------RECEIVING RESPONSE-------------------------------------------------------

                printf("client: Receiving response.\n");
                total_bytes = 0;        


                while (1)
                {
                    bytes_sent = 0; bytes_recv = 0;
                    memset(&buffer, 0, sizeof buffer );
                    if ((bytes_recv = recv(re_fd, buffer, 4096, 0)) == 0)         //receive part
                    {
                        break;
                    }

                    printf("Received part (%d bytes)\n", bytes_recv);

                    //showpart = 1;

                    if (showpart)
                    {
                        printf( "----------PART-----------\n"
                                "%s\n"
                                "-------------------------\n", buffer);
                    }

                    bytes_sent = send(new_fd, buffer, strlen(buffer), 0);
                    printf("Sent part (%d bytes)\n", bytes_sent);

                    total_bytes += bytes_sent;  
                }   

                break;
            }

            //showpart = 1;

            if (showpart)
            {
                printf( "----------PART-----------\n"
                        "%s\n"
                        "-------------------------\n", buffer);
            }

            bytes_sent = send(new_fd, buffer, strlen(buffer), 0);
            printf("Sent part (%d bytes)\n", bytes_sent);

            total_bytes += bytes_sent;  

        }


        close(web_fd);

        printf("Done\nBytes sent to browser: %d\n", total_bytes);

        puts("\nEnd client\n");

        close(new_fd);
        }


    close (sock_fd);

    return 0;
}

1 个答案:

答案 0 :(得分:3)

在将任何数据发送到客户端之前,您需要保留代理中的所有数据。这意味着您还必须了解足够的HTTP协议以了解响应何时完成。如果您需要支持HTTP / 1.1,则意味着您需要支持分块编码。

此外,您的重定向不是合法的HTTP。它有一个请求标头,但没有指定支持请求标头的HTTP版本。

你还有很多其他错误,包括访问数组越界,并使用strlen来获取除C风格字符串以外的其他内容。您调用read并丢弃返回值,因此您不知道必须发送到另一端的字节数。老实说,似乎你正在尝试一项超出基本编程知识的编程任务。在编写过滤代理之前,正确处理二进制数据的事情就已经过去了。