我正在尝试在C中创建一个小的Web代理。首先,我正在尝试获取一个网页,并将Get Frame发送到服务器。我不知道我错过了什么,但是我没有收到任何回应。如果您可以帮助我找到此代码中缺少的内容,我将非常感谢。

int main (int argc, char** argv) {
   int cache_size,     //size of the cache in KiB
       port,
       port_google = 80,
       dir,
       mySocket,
       socket_google;

   char google[] = "www.google.es", ip[16];
   struct sockaddr_in socketAddr;
   char buffer[10000000];

   if (GetParameters(argc,argv,&cache_size,&port) != 0)
       return -1;

   GetIP (google, ip);
   printf("ip2 = %s\n",ip);

   dir = inet_addr (ip);
   printf("ip3 = %i\n",dir);

   /* Creation of a socket with Google */
   socket_google = conectClient (port_google, dir, &socketAddr);
   if (socket_google < 0) return -1;
   else printf("Socket created\n");

   sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
   if (write(socket_google, (void*)buffer, MESSAGE_LENGTH+1) < 0 )
       return 1;
   else printf("GET frame sent\n");

   strcpy(buffer,"\n");
   read(socket_google, buffer, sizeof(buffer));

   // strcpy(message,buffer);
   printf("%s\n", buffer);

   return 0;
}

这是我用来创建套接字的代码。我认为这部分还可以,但是我会复制它,以防万一。

int conectClient (int puerto, int direccion, struct sockaddr_in *socketAddr) {
   int mySocket;
   char error[1000];

   if ( (mySocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
       printf("Error when creating the socket\n");
       return -2;
   }

   socketAddr->sin_family = AF_INET;
   socketAddr->sin_addr.s_addr = direccion;
   socketAddr->sin_port = htons(puerto);

   if (connect (mySocket, (struct sockaddr *)socketAddr,sizeof (*socketAddr)) == -1) {
       snprintf(error, sizeof(error), "Error in %s:%d\n", __FILE__, __LINE__);
       perror(error);
       printf("%s\n",error);
       printf ("-- Error when stablishing a connection\n");
       return -1;
   }
   return mySocket;
}

谢谢!

有帮助吗?

解决方案

由于您没有发布 GetIP 例行程序,我不确定您的主机名查找是否正确,从外观上看,我不确定您正在使用 inet_addr 功能正确。

尼古拉指出了一些非常好的观点(我完全同意)。实际上你 GET 请求实际上被打破了,当我在系统上的本地Apache Web服务器上测试它时,它无效。

sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
if (write(socket_google, (void*)buffer, LONGITUD_MSJ+1) < 0 )
    return 1;
else printf("GET frame sent\n");
...

strcpy(buffer,"\n");
read(socket_google, buffer, sizeof(buffer));

应该替换

  snprintf(buffer, sizeof(buffer), 
      "GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: TEST 0.1\r\n\r\n", 
      google);

  if (write(socket_google, buffer, strlen(buffer)+1) < 0 ) {
      close(socket_google);
      return 1;
  } else 
      printf("GET frame sent\n");
  ...

  buffer[0] = '\0';
  /* Read message from socket */
  bytes_recv = read(socket_google, buffer, sizeof(buffer));
  if (bytes_recv < 0) {
       fprintf(stderr, "socket read error: %s\n", strerror(errno));
       close(socket_google);
       exit(10);
  }

  buffer[bytes_recv] = '\0';    /* NUL character */

  /* strcpy(message,buffer); */
  printf("%s\n", buffer);

  ...

你也应该 close 退出程序之前的插座。启用编译器的标准C89/90或C99模式(例如 -std=c99 对于GCC)并启用警告(例如 -Wall 对于GCC),并阅读它们。和 #include 功能原型的必要标头文件(假设Linux):

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>      /* for gethostbyname() */

有一些 铸件 指针和 struct关于主机名 / IP地址解决方案的s,这可能会令人困惑且容易犯错,因此请验证您按照您的期望工作的工作。

 in_addr_t ip;
 ...

 GetIP(google, &ip);   /* I changed the parameters */
 printf("IP address = %x (%s)\n", 
     ip, 
     inet_ntoa(*((struct in_addr*)&ip)));

其他提示

首先,您没有检查多少个字节 write(2) 呼叫实际写信给插座。呼叫的返回值告诉您。也是如此 read(2). 。 TCP插座是双向流,因此通常在循环中始终执行两者,直到转移预期的字节数, EOF 读取(从 read(2)),或发生错误(阅读时您都没有检查)。

那么HTTP是相当复杂的协议。让自己熟悉 RFC 2616, ,特别是应用程序级别连接管理和传输编码。

编辑0:

嗯,没有“简单”代理。您需要管理多个连接(至少客户到proxy和proxy-to-server),因此最好研究 select(2)/poll(2)/epoll(4)/kqueue(2) 系统呼叫家庭,这使您可以 多路复用 我/o。这通常与 非障碍 插座。查看辅助图书馆 libevent. 。查看在良好的网络服务器/代理中如何完成此操作 nginx. 。听起来您可以发现很多东西,但是请放心,这很有趣:)

实际上,我一直在使用名为RZSocket的库实现一个小型网络代理 链接到它.

我在实施Web代理时发现的最困难的事情之一,也许这也许也是您的问题,是为了使代理工作正常工作,我不得不设置“远景”设置错误。在Firefox中这样做的一种方法是访问 关于:config 地址,并设置 network.http.proxy.keep-alivefalse.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top