Avatar billede duper Nybegynder
03. november 2002 - 01:10 Der er 4 kommentarer og
1 løsning

Registere om der modtages flere data

Jeg arbejder på et studie-projekt omhandlende udvikling af proxy-server.

Jeg arbejder med connection-oriented forbindelser.

Problemet er forbindelsen mellem min proxy og web-serveren.
Ved HTTP 1.0: Når web-serveren har sendt alle data lukker den forbindelse og dette kan jeg registrere ved at recv() returnerer 0.
Ved HTPP 1.1: Web-serveren lukker ikke forbindelsen, når den har sendt alle data.
Hvordan kan jeg som klient registere om web-serveren er færsig med at sende?

Jeg har prøvet følgende:
Indsætte et alarm signal, men recv() blokerer, så alarm bliver aldrig udløst.

Undersøge det sidst modtage tegn, som ofte er ASCII-værdien 10. Virker måske i 95% af tilfældene.

Håber i kan komme med nogle ideer/forslag til løsning af dette.

/Sune

Sprog: C (ikke C++)
OS: Linux

--- Udrag af koden ---
//PROGRAM KODE
//FUNKTION: Main
int main(int argc, char *argv[])
{
  int sockfd;
  int newsockfd;
  pthread_t thr;

  struct sockaddr_in server;

  //Ignorer Broken pipe
  signal(SIGPIPE, SIG_IGN);

  if(argc!=2)
  {
    exit(1);
  }

  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = INADDR_ANY;
  server.sin_port = htons (atoi(argv[1])); // port should be a parameter

//Bind
if(bind(sockfd, (struct sockaddr*) &server, sizeof(server)))
  {
      perror("Fejl: Bind");
      close(sockfd);
      exit(2);
  }

  //Listen
  if(listen(sockfd,25)==-1)
  {
      perror("Fejl: Listen");
      exit(3);
  }

  //Opretter ny thread for hver ny connection
  while (1)
  {
      newsockfd = (int)accept(sockfd, NULL, NULL);
      pthread_create(&thr, NULL, (void *)forbindelse_oprettet, (int*)newsockfd);
  }
}

//FUNKTION; forbindelse_oprettet
int forbindelse_oprettet(int newsockfd)
{
        struct hostent *h;

        char symbolfolge[50][80];//URL lexet i symboler
        char inputData[1001];//URL'en modtaget fra klienten

        int recva;//retur-værdien fra recv()
        int senda;//retur-værdien fra send()

        recva=recv(newsockfd, (char *)&inputData, 1000, 0);

        //Lexer
        if(lexer(inputData, symbolfolge)==1)
        {
        }
        //Parser
        else if(parser(symbolfolge)==1)
        {
        }
        //Requester hostname
        else if((h=gethostbyname(symbolfolge[2]))==NULL)
        {
            herror("Fejl: gethostbyname");
        }
        else
        {
            int sockfd;
            struct sockaddr_in client;
            int retry_connect=1;
            int retry_send=1;

            //TCP - connection
            sockfd = socket(AF_INET, SOCK_STREAM, 0);

            client.sin_family = AF_INET;
            client.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr *)h->h_addr)));
            client.sin_port = htons(80);

            //Connect til web-server
            for(;retry_connect<6 && retry_connect!=0;)
            {
                if(connect(sockfd, (struct sockaddr*) &client, sizeof(client))==-1)
                {
                    perror("Fejl: Connect: Forbindelse til webserver");
                    sleep((retry_connect));
                    retry_connect++;
                }
                else
                {
                    retry_connect=0;
                }
            }

            //Videre sendelse af header fra browser til web-server
            for(;retry_send<6 && retry_send!=0;)
            {
                if(send(sockfd, &inputData, recva,0)==-1)
                {
                    sleep(retry_send);
                    retry_send++;
                }
                else
                {
                    retry_send=0;
                }
            }
            modtagBinary((int*)newsockfd, (int*)sockfd);
            //Lukker forbindelsen til web-server
            close(sockfd);
        }
    //Lukker forbindelsen til browser
    close(newsockfd);
    //Nedlægger thread
    pthread_exit(NULL);
}

void modtagBinary(int newsockfd, int sockfd)
{
    int buffer_str
    unsigned char outputDataBinary[buffer_str];

    int recva=buffer_str;//
    int senda=buffer_str;
    int retry_send;

    for(;recva>1;)
    {
        bzero(outputDataBinary, 1000);
        //Modtager fra web-server
        recva=recv(sockfd, &outputDataBinary, 1000, 0);
        if(recva==0 || recva==-1)
        {
            return;
        }
        else
        {
            retry_send=0;
            for(;retry_send<5 && retry_send!=-1;)
            {
                //Videre sendelse af data til browser
                senda=send(newsockfd, &outputDataBinary, recva, 0);
                if(senda!=recva)
                {
                    //Venter inden nyt forsøg
                    sleep(retry_send);
                    retry_send++;
                }
                else
                {
                    retry_send=-1;
                }
            }
        }
       
        //Kontrollerer om sidste byte er ASCII-værdien 10
        if(outputDataBinary[(recva-1)]==10)
        {
            return;
        }
    }
}
Avatar billede mickni33 Nybegynder
03. november 2002 - 09:13 #1
Et lille gæt:
sæt den til at registrere at det sidste tegn er '\0'
Ved ikke lige om det er det samme som recv ascii=10
Avatar billede arne_v Ekspert
03. november 2002 - 09:36 #2
Web-serveren bør sende en HTTP-header
Content-Length med antallet af bytes i
content !
Avatar billede duper Nybegynder
03. november 2002 - 12:09 #3
Til mickni33:
web-serveren sender desværre ikke et '\0' (ASCII-værdi 0), som sidste byte, men som skrevet i indlægget: ofte ACSII-værdi 10 (Line feed).

Til arne v:
Så vidt jeg ved, er det vist kun nogle gange at Content-length fremgår i HTTP-header fra web-serveren. Jeg undersøger det lige inde på w3.org og skriver tilbage senere.
Avatar billede franknielsen Nybegynder
03. november 2002 - 19:33 #4
Du kan bruge ioctlsocket(..) til at se om der er pending bytes, men den er stadig ikke helt sikker da der kan opstå et hul tids messigt på hvornår serveren sender. Fx kan den sende header data og så udføre et database opslag der tager tid og så der efter sende resten. Det bedste jeg kan forslå er at læse RFC'erne for HTTP trafikken, der burde de enkelte senarier være beskrevet!

Content-Length headeren bliver ikke altid brugt, kun hvis siden er statisk!

Et alternativ kunne være at lave jeres problem stilling på en server og med en IE browser sniffe IP trakfikken og se hvordan data opføre sig på netværket. Der findes tcpdump for linux og windump for windows - ikke den hurtigste må at løse problemet på.

Cheers, Frank
Avatar billede stephenmaa Nybegynder
26. november 2002 - 01:17 #5
Hvis der bruges kepp-alive HTTP connections standard i http 1.1 - kan detekteres på header feltet "Connection: Keep-Alive" kan klienten vælge at droppe forbindelsen - du bliver derfor nødt til enten at holde den i live indtil din klient nedlægger den - eller lade den time ud og så lukke den fra proxy´ens side. Der kunne jo være at en anden af dine klienter vil hente fra den aktuelle server.

Alternativt kan serveren vælge at lukke forbindelsen explicit - det ser du med et null-read fra din socket (recva==0)


Hvis ikke du indsætter de korrekte proxy informationer i "via" feltet skal du nok passe på med at genbruge den aktive connection på vegne af en anden klient på grund af sikkerheds spørgsmål og state-aware server side scripts.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester