2017-05-14 53 views
-3

我想实现一个简单的代理服务器,迄今为止很好,我设法正确地做GET方法,但现在我必须为它实现缓存。其背后是想法,当我得到下面的命令:与缓存系统代理实现

  • GET www.google.com
  • GET www.cplusplus.com
  • GET www.google.com

的第二次我被要求从谷歌获取信息,它应该来自我的缓存系统。我一直在想,做这件事的最好方法是实现一个简单的文件系统,将我收到的信息存储在文件中,然后每当我找到文件时就读取它。唯一的麻烦是我无法创建文件,如http://elf.cs.edu.ro/

这是我的代码,所以你明白我在做什么。

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

void error(char* msg) { 
    perror(msg); 
    exit(0); 
} 

int main(int argc,char* argv[]) { 

int count = 0; 
FILE *in; 
FILE *out; 
pid_t pid; 
struct sockaddr_in addr_in,cli_addr,serv_addr; 
struct hostent* host; 
int sockfd,newsockfd; 

if(argc<2) 
    error("./proxy <port_no>"); 

printf("\n*****WELCOME TO PROXY SERVER*****\n"); 

bzero((char*)&serv_addr,sizeof(serv_addr)); 
bzero((char*)&cli_addr, sizeof(cli_addr)); 

serv_addr.sin_family=AF_INET; 
serv_addr.sin_port=htons(atoi(argv[1])); 
serv_addr.sin_addr.s_addr=INADDR_ANY; 


sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
if(sockfd<0) 
    error("Problem in initializing socket"); 

if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0) 
    error("Error on binding"); 


listen(sockfd,50); 
int clilen=sizeof(cli_addr); 



startpoint: 

newsockfd=accept(sockfd,(struct sockaddr*)&cli_addr,&clilen); 

if(newsockfd<0) 
error("Problem in accepting connection"); 

pid=fork(); 
//printf("Pid is: %d\n", pid); 
if(pid==0) { 
    sites saves[10]; 
    int noOfSites = 0; 
    struct sockaddr_in host_addr; 
    int flag=0,newsockfd1,n,port=0,i,sockfd1; 
    char buffer[510],t1[300],t2[300],t3[10], aux[510]; 
    char* temp=NULL; 
    bzero((char*)buffer,500); 
    recv(newsockfd,buffer,sizeof(buffer),0); 
    //printf("%s\n",buffer); 
    sscanf(buffer,"%s %s %s",t1,t2,t3); 
    //printf("%s\n",buffer); 

    if (((strncmp(t1,"GET",3)==0))&&((strncmp(t3,"HTTP/1.0",8)==0)||(strncmp(t3,"HTTP/1.0",8)==0))&&(strncmp(t2,"http://",7)==0)) { 
     strcpy(t1,t2); 
     int saved = 0; 
     flag=0; 

     for(i=7;i<strlen(t2);i++) { 
      if(t2[i]==':') { 
       flag=1; 
       break; 
      } 
     } 
     // printf("The site to GET is : %s\n",t2); 
     temp=strtok(t2,"//"); 
     if (flag==0) { 
      port=80; 
      temp=strtok(NULL,"/"); 
     } 
     else { 
      temp=strtok(NULL,":"); 
     } 

     sprintf(t2,"%s",temp); 
     host=gethostbyname(t2); 

        int it; 
      for (it = 0; it < noOfSites; it++){ 
      printf("Site saved is: %s\n", saves[it].site); 
      if (strcmp(saves[it].site,t2) == 0){ 
       saved = 1; 
       out = fopen(t2, "r"); 
       printf("We have cache!\n"); 
      } 
     } 
     if(flag==1) { 
      temp=strtok(NULL,"/"); 
      port=atoi(temp); 
     } 


     strcat(t1,"^]"); 
     temp=strtok(t1,"//"); 
     temp=strtok(NULL,"/"); 
     if(temp!=NULL) 
      temp=strtok(NULL,"^]"); 


     bzero((char*)&host_addr,sizeof(host_addr)); 
     host_addr.sin_port=htons(port); 
     host_addr.sin_family=AF_INET; 
     bcopy((char*)host->h_addr,(char*)&host_addr.sin_addr.s_addr,host->h_length); 

     sockfd1=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
     newsockfd1=connect(sockfd1,(struct sockaddr*)&host_addr,sizeof(struct sockaddr)); 
     sprintf(buffer,"\nConnected to %s IP - %s\n",t2,inet_ntoa(host_addr.sin_addr)); 
     if(newsockfd1<0) 
      error("Error in connecting to remote server"); 

     bzero((char*)buffer,sizeof(buffer)); 
     if(temp!=NULL) 
      sprintf(buffer,"GET /%s %s\r\nHost: %s\r\nConnection: close\r\n\r\n",temp,t3,t2); 
     else 
      sprintf(buffer,"GET/%s\r\nHost: %s\r\nConnection: close\r\n\r\n",t3,t2); 




     if (saved == 1){ 
      printf("Are we ever here\n"); 
      n = send(sockfd1,buffer,strlen(buffer),0); 
      char * line = NULL; 
      size_t len = 0; 
      ssize_t read; 
      int count = 0; 
      if (n<0) 
       error("Error writing to socket"); 
      else { 
       while ((read = getline(&line, &len, out)) != -1) { 
        //printf("Retrieved line of length %zu :\n", read); 
        if (count > 0) 
         write(newsockfd,line,read); 
        if (strcmp(line,"\r\n") == 0) 
         count++; 
       } 
      } 
     } 

     if (saved == 0){ 
      //printf("We are only here\n"); 
      strcpy(saves[noOfSites].site,t2); 
      noOfSites++; 
      printf("The new site file is: %d\n", noOfSites); 


      in = fopen(t2,"w"); 
      n=send(sockfd1,buffer,strlen(buffer),0); 
      printf("I have opened for writing: %s\n\n\n\n\n\n",t2); 

      if(n<0) 
       error("Error writing to socket"); 
      else { 
       do { 
        memset(buffer, 0, sizeof(buffer)); 
        n=recv(sockfd1,buffer,sizeof(buffer),0); 
        fwrite(buffer, n, 1, stdout); 
        printf("\n"); 
        fwrite(buffer, n, 1, in); 
        if(!(n<=0)) 
         write(newsockfd,buffer,n); 
       } while(n>0); 
      } 
     } 
    } 
    else { 
     send(newsockfd,"400 : BAD REQUEST\nONLY HTTP REQUESTS ALLOWED",18,0); 
    } 
    close(sockfd1); 
    close(newsockfd); 
    close(sockfd); 
    fclose(in); 
    return 0; 
} 
else { 
    close(newsockfd); 
    goto startpoint; 
} 
return 0; 
} 

任何人都可以请我指出正确的方向吗?我不希望有人为我做这件事,只是关于如何做这件事的一些想法,所以我可能有机会。感谢您的时间!

+1

寻求调试帮助的问题(“**为什么不是这个代码工作?”)必须包含所需的行为,特定的问题或错误以及必须**的最短代码**在问题本身中重现。没有明确问题陈述的问题对其他读者无益。请参阅:[如何创建最小,完整和可验证示例。](/ help/mcve) –

回答

0

您正在寻找一个通用的键/值数据存储。您可以在内存中使用哈希表,使用简单的数据库(如gdbm),或者选择更高级的数据库(如MongoDB)。

0

如果我在这个过程中犯了一些错误,并且我没有发布很好的问题,我真的很抱歉,但是我已经设法自己找出这个问题了。我遇到的麻烦是,当我试图创建文件来存储我的信息从get命令,我试图创建文件的名称,如:http://something.com/它不会让我作为/被禁止当试图创建文件从C程序(或者我已经理解)。我的任务很简单,用/替换其他的东西(在我的情况下),这一切都很顺利。谢谢你的努力,如果我让你们在试图了解我在说什么的时候失去了时间,我真的很抱歉。

所以更准确地说,我试图做的是当我第二次接收get命令时(同一个get命令具有相同的链接)我需要从我创建的第一个文件中获取信息我收到命令的时间。它应该是这样的:

  • GET www.something.com HTTP/1.0 - >我需要创建一个名为“www.something.com”文件,存储来自该网站的所有信息在该文件然后关闭它,当然,将该信息发送到通信打开的套接字
  • GET www.something.com HTTP/1.0 - >我需要打开由上一个命令创建的文件,并获取要发送的信息从那个文件

再次,对不起,如果我已经困扰了一个人。非常感谢你!