Avatar billede duper Nybegynder
23. oktober 2002 - 15:26 Der er 7 kommentarer og
1 løsning

Net: Hvordan får jeg Recv() til at vente uden sleep

Jeg er igang med en studie opgave omhandlende en proxy-server. Problemet omfatter forbindelsen mellem proxy'en og web-serveren.

Jeg har oprettet en connection-oriented forbindelse mellem proxy og web der virker.

Jeg bruger send(), til at sende HTTP-requesten fra klient browseren. 
Herefter bruger jeg recv() til at modtage data fra web-serveren.

Selve problemet er, at programmet begynder at recv() før web-serveren får svaret, så jeg er tvunget til indsætte en sleep() på 2 sec mellem send() og recv(), for at programmet virker.

Jeg søger derfor idéer/froslag til hvorledes jeg får programmet til at virke uden sleep(), da det forringer performance betydeligt.

På forhånd tak for forslagene :)
/Sune

Sporg: C (ikke C++)
OS: Linux
Proxy'en opretter en tråd/thread for hver connection

Uddrag af koden:
send (sockfd, &inputData, (strlen(inputData)+1), 0);
sleep(2); //Denne til jeg gerne have væk
recv (sockfd, &outputData, 1000000, 0);
Avatar billede soepro Nybegynder
23. oktober 2002 - 15:44 #1
duper >> Når du siger forringer performance, så er det vel fordi sleep(2) -2 millisekunder- tager for lang tid eller ?

recv() metoden, fortæller den dig ikke om du fik noget retur ?

I følge MSDK hjælpen, så venter recv() med mindre din socket er nonblocking - kunne du ændre noget omkring det i oprettelsen af socket'en ?
Avatar billede soepro Nybegynder
23. oktober 2002 - 15:47 #2
er problemet/behovet for sleep i grunden ikke kun første gang ? hvad med at bruge den viden:

send(...);
if (firstTime)
{
  firstTime = false;
  sleep(2);
}
recv(...);

Eller lave en egentlig retry loop den f.eks. prøver at connecte i 1 sekund:

const int delay = 2; // Prøv med 2 ms mellemrum.
:
if (firstTime)
{
  firstTime = false;
  int count = 1000/delay;
  while (count--)
  {
    if (recv() >= 0)
      break;
    sleep(delay);
  }
}
else
  recv();

    if
Avatar billede soepro Nybegynder
23. oktober 2002 - 15:47 #3
Skulle have været et svar.
Avatar billede smokes Nybegynder
23. oktober 2002 - 16:03 #4
Hej Duper

når du opretter en socket bliver den oprettet som en blocking socket per default.. Det betyder at hvis du kalder recv() så "blocker" recv() indtil den har modtaget data, som den derefter returnerer til dit program. At den blocker vil sige at funktionen ikke returnerer til dit program førend der er data at hente. recv() returnerer et tal som er det antal bytes der er blevet kopieret til den buffer du specificerede i kaldet. Du skal være opmærksom på at recv() ikke nødvendigvis modtager det antal du har bedt den om (skyldes beslutninger i IP laget i kernel). Derfor er du nød til at tjekke returværdien og hvis alle bytes'ne ikke er læst.. så læse den igen indtil du har det hele :-).. Ikke for at fornærme dig men din brug af
recv() virker ikke.. du kan ikke kalde den EN gang og forvente at modtage tæt på en megabyte (1000000 bytes). Dette skyldes at KERNEN i linux (og alle andre OS'er som implementerer en TCP/IP stack) bryder din TCP stream op i packets. Hvis du er heldig kan du sende 64 kb på en gang.. Men selvom du kalder recv() forkert burde den stadigvæk blocke og dit sleep() kald burde være unødvendigt (btw brug ALDRIG sleep() til den slags *s*). Dette leder mig til at tro at du måske bruger nonblocking sockets. For at kontrollere disse skal du under linux bruge select() kaldet (kan også med fordel bruges på blocking sockets).. Select er temmelig avanceret men kort forklaret er det en funktioner der fortæller dig om dine socket(s) er klar til blive læst fra, skrevet til eller om de har "raised exceptions" (at der er opstået fejl). Jeg kan ikke forklare dig select() kaldet i detaljer her, men du kan slå det op. Forresten gælder det samme for send() som for recv(), du kan ikke være sikker på at samtlige bytes bliver sent på en gang. Derfor skal du ALTID tjekke returværdien *s*.. Mit råd til dig er at læse lidt op på socket programmering.. her er to gode links:

// godt site der med små tutorials forklarer hvordan du bruger BSD sockets (dem du bruger) under unix (som i denne forbindelse er det samme som linux)

http://www.ecst.csuchico.edu/~beej/guide/net/html/

og

http://tangentsoft.net/wskfaq/

// winsock faq'en.. handler godt nok om windows socket men det er stort set det samme som linux sockets udadtil (flere funktioner og anderledes initializering).. Men der er en masse gode forklaringer

Kan du slet ikke få det til at virke så kan du eventuelt maile mig sourcekoden.. så kigger jeg på den.. har dog ikke mulighed for at teste den i det jeg ikke kører linux :-).. men kan ihvertfald spotte de største fejl og mangler :-)

håber du kunne bruge det til noget..

Tilsidst vil jeg lige nævne at TCP/IP programmering er et temmelig avanceret område.. det kan godt tage lidt tid at forstå det hele så du skal ikke lade dig slå ud hvis det ikke virker de første 10-50 gange.. det gjorde heller ikke for mig :-)
Avatar billede smokes Nybegynder
23. oktober 2002 - 16:07 #5
soepro: ikke for at flame dig eller noget.. men den måde at skrive socket programmering er forkert og udtryk for en manglende viden om emnet.. læs de to resourcer jeg har linket til.. det eneste rigtige (på en unix platform) er at bruge på select() kaldet og reagere ud fra det.. jeg indrømmer dog at select() er et bæst, men det er ikke svært når man først har sat sig ind i det *s*.. på windows platformen VI koder for kan man bruge overlapped IO, port completion, samt WSA* funktioner det sender notification i form af windows messages :-)
Avatar billede duper Nybegynder
23. oktober 2002 - 16:40 #6
Til smokes:
Tak for dit svar. Du har givet mig en del af arbejde med


NB: Giver aldrig op, men er ofte tæt på at smide PCen ud af vinduet :0)
Avatar billede smokes Nybegynder
23. oktober 2002 - 16:48 #7
duper: lad være med det.. det der gør "bæstet" spændende set med mine øjne er udfordringerne *s*.. er ved at skrive en god solid wrapper til winsock.. den understøtter blocking sockets fuldt ud indtil videre så hvis din platform var win32 måtte du gerne benytte den.. men på den anden side er det jo bedre hvis du lærer det selv :-)
Avatar billede soepro Nybegynder
29. oktober 2002 - 11:30 #8
smokes >> Du har eet - min viden omkring sockets er begrænset til at jeg kan lave en simpel kommunikation mellem en server og en client. Min pointe var derfor også det mere principielle i at lave en sleep() som reaktion på det problem duper oplevede. (Nemlig at det kun var første gang.)

Det korrekte vil selvfølgelig være at checke om socket'en er klar - det er der bare indtil nu ikke nogen der har kunnet forklare. select() er så åbenbart svaret på det.
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