2017-05-14 57 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 - >我需要打開由上一個命令創建的文件,並獲取要發送的信息從那個文件

再次,對不起,如果我已經困擾了一個人。非常感謝你!