Сокеты C: переслать запрос на порт 80 и прочитать ответ - PullRequest
0 голосов
/ 15 августа 2011

У меня есть следующий код (я работаю с кодом на http://www.linuxhowtos.org/C_C++/socket.htm), который я пытаюсь превратить в прокси-сервер:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

void dostuff(int); /* function prototype */
void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
     //setup proxy:
     int sockfd, newsockfd, portno, pid;
     socklen_t clilen;
     struct sockaddr_in serv_addr, cli_addr;

     if (argc < 2) {
         fprintf(stderr,"***ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0)
        error("***ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0)
              error("***ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     while (1) {
         newsockfd = accept(sockfd,
               (struct sockaddr *) &cli_addr, &clilen);
         if (newsockfd < 0)
             error("***ERROR on accept");
         pid = fork();
         if (pid < 0)
             error("***ERROR on fork");
             if (pid == 0)  {
             close(sockfd);
             dostuff(newsockfd);
             exit(0);
         }
         else close(newsockfd);
     } /* end of while */
     close(sockfd);
     return 0; /* we never get here */
}

/******** DOSTUFF() *********************
 There is a separate instance of this function 
 for each connection.  It handles all communication
 once a connnection has been established.
 *****************************************/
void dostuff (int sock)
{
   int n;
   char buffer[256];

   bzero(buffer,256);
   n = read(sock,buffer,255);
   if (n < 0){
       error("***ERROR reading from socket");
   }
   //printf("Here is the message: %s\n",buffer);




   /*
   ***Forward message to port 80 and read response here
   */





   n = write(sock,"I got your message",18);
   if (n < 0) error("***ERROR writing to socket");
}

В функции «dostuff» я хочу записать «буфер» на порт 80, прочитать ответ и записать этот ответ обратно через порт 20000 (argv [1]).

В тот момент, когда я устанавливаю прокси моего браузера на 172.16.1.218:20000, все, что я получаю, это "Я получил ваше сообщение". Я хочу изменить это на ответ с веб-страницы!

Любые указатели в правильном направлении очень ценятся.

Вот то, что я попробовал sofar (замените многострочный комментарий «Переслать сообщение на порт 80 и прочитать ответ здесь» этим кодом):

   int sockfdi, portnoi, ni;
   struct sockaddr_in serv_addri;
   struct hostent *serveri;
   portnoi =80;

   sockfdi = socket(AF_INET, SOCK_STREAM, 0);
   if (sockfdi < 0){
        error("***ERROR opening socket");
   }
   serveri = gethostbyname("172.16.1.218");
   if (serveri == NULL){
       fprintf(stderr,"***ERROR, no such host\n");
       exit(0);
   }

   bzero((char *) &serv_addri, sizeof(serv_addri));
   serv_addri.sin_family = AF_INET;
   bcopy((char *)serveri->h_addr, (char *)&serv_addri.sin_addr.s_addr, serveri->h_length);
   serv_addri.sin_port = htons(portnoi);
   if (connect(sockfdi,(struct sockaddr *) &serv_addri,sizeof(serv_addri)) < 0){
       error("***ERROR connecting");
   }
   printf("Please enter the message: ");
   bzero(buffer,256);

Но каждый раз, когда я пытаюсь подключиться через веб-браузер, сервер выдает: «*** ОШИБКА подключения: соединение отклонено»

Большое спасибо заранее,

1 Ответ

1 голос
/ 15 августа 2011

Это нетривиальное задание, которое вы намеревались выполнить.В настоящее время вам не хватает трех вещей, простых и двух сложных:

  1. Вы должны открыть сетевое соединение с сервером, на который хотите переадресовать вызов (довольно просто,см. socket() и connect()).

  2. Затем у вас будет дуплексное соединение, то есть два одновременных потока данных, один из которых будет передаваться от клиента к перенаправленному серверу, а другой -с переадресованного сервера клиенту.Чтобы справиться с этим параллелизмом, вам нужны либо два потока с блокирующим вводом / выводом, либо какой-то неблокирующий ввод / вывод (см. select() или AIO).

  3. ЕслиВы перенаправляете HTTP-запрос без изменений на другой сервер, и, скорее всего, в запросе у вас будут неверные имена серверов и IP-адреса.Запрос будет отклонен.Поэтому вам нужно проанализировать HTTP-заголовок, выполнить некоторые замены и переслать измененный HTTP-запрос.

...