Avatar billede mollevp Nybegynder
15. august 2005 - 21:41 Der er 15 kommentarer og
1 løsning

2 x read på socket giver problemer.

Hejsa alle,
Jeg står med følgende kode (jeg har renset lidt ud i den - fjernet nogle løkker der indlæser resulterne osv. burde ikke have nogen betydning for problemet):


  memset(buf,'\0',sizeof(buf));
 
  // Direct stream status - send request to switch device
  strcpy(command,"session direct stats show");
  send_command(sd,peer,command);
 
  // Resetting counter used when reading stats from switch device
  ix = 0;

  // Looping as long as there is something to read
  while((recv_status = recv(sd, buf+ix, sizeof(buf)-ix-1, 0)) > 0){
    ix = ix + recv_status;
  }

  if(recv_status == -1) perror("Socket");

  // Parses the result
  extract_stats_data(buf, data, 0);


  // For the direct stream the result is stored in the first struct
  ... kode der gemmer resultater ...

  // Sendt reset to switch device
  strcpy(command,"session direct stats reset");
  send_command(sd,peer,command);

  // reset the buffer
  memset(buf, '\0', sizeof(buf));   
 
  // Broadcast stream status - send request to switch device
  strcpy(command,"session bc stats show");
  send_command(sd, peer, command);
   
  // Resetting counter used when reading stats from switch device
  ix = 0;

  // Looping as long as there is something to read
  while((recv_status = recv(sd, buf+ix, sizeof(buf)-ix-1, 0)) > 0){
    ix = ix + recv_status;

    printf("BYTES LAEST: %d\n", recv_status);
  }

  if(recv_status == -1) perror("Socket");
 

  // Parse the recived data from the switch device
  extract_stats_data(buf, data, 1);
 
  ... kode der gemmer resultater ...

  }
 
  // Sendt reset to switch device
  strcpy(command, "session bc stats reset");
  send_command(sd, peer, command);
 
  fflush(stdout);

Koden gør følgende:
1. Sender en forespørgsel på data direkte fra server
2. Læser resultatet
3. Sender en forespørgsel på data fra andre klienter (broadcast)
4. Læser resultatet

Problemet viser sig på følgende måde:

1. Køres den første while loop der læser, kommer vi aldrig ind i nr.2
2. Køres de to while loops hver for sig (dvs. med den ene udkommenteret) kører det fint..
3. Køres kun den sidste læse-while-loop altså jeg sender begge forespørgsler til vores switch device før jeg læser får jeg fint resultatet fra begge forespørgsler tilbage..

Jeg har før haft problemer med at sende flere forespørgsler til en socket lige i træk.. Er der noget jeg skal være opmærksom på her?
Den socket jeg prøver at læse fra er sat til non-blocking.

Her er foresten koden der sender forespørgslen (funktionen send_command):

void send_command(int sd, struct sockaddr_in peer,char *command)
{
  int send_status;
 
  strcat(command,"\n");

  send_status = send(sd, command, strlen(command), 0);
  if(send_status == -1) perror("send_command()");

}

Håbr i kan hjælpe.. MVH Morten
Avatar billede mollevp Nybegynder
15. august 2005 - 22:06 #1
Findes der nogle "ting" man skal huske hvis man sender/læser fra en socket 2 gange i træk?
Avatar billede arne_v Ekspert
15. august 2005 - 23:46 #2
muligvis er der igen dele problemer

du skriver 2 gange, men kan alligevel læse 1, 2, 3 eller flere gange

har du mulighed for at læse til \n og så gå videre til næste ?
Avatar billede mollevp Nybegynder
16. august 2005 - 08:37 #3
Grunden til jeg har lavet det så den læser mere end en gang - er at jeg vil være sikker på at få hele resultatet.. Jeg kunne som du siger også læse til jeg har en eller anden form for terminering af input..

Jeg tror jeg laver det om så jeg sender begge forespørgsler og så læser hele resultatet en gang.. Det ser nemlig udtil at virke..

En af problemerne er også lidt, at selvom jeg laver den blocking. Vil den aldrig stå og vente på input, da der altid (næsten) bliver smidt 4 bytes tilbage - så læser den bare dem og er videre..

Og da jeg havde den på blocking og ikke havde recv inde i en while - fik jeg tit kun dele af resultatet.. Resten kom så senere i næste læsning..

Alle gode ideer modtaget :)
Avatar billede mollevp Nybegynder
16. august 2005 - 09:24 #4
Jeg forstår bare ikke helt hvad der kan går galt..

- Jeg sender en forespørgsel
- Jeg læser resultatet til der ikke er mere
- Jeg sender en ny forespørgsel
- Jeg prøver at læse resultatet, men da vi ikke kommer ind i den sidste læse-while løkke må det være fordi der ikker er noget at læse..

Udkommenteret hver for sig virker det.. Men kun en læsning virker det.. Hvorfor må jeg ikke læse det første resultat og derefter det næste - hvad kan der være galt i det??
Avatar billede arne_v Ekspert
16. august 2005 - 09:33 #5
du læser ikke både første og anden kommando i første læs ?
Avatar billede mollevp Nybegynder
16. august 2005 - 09:37 #6
Jo, det ser det faktisk ud til.. jeg fatter det ikke - jeg sender jo først nr2 forespørgsel efter jeg har lavet den recv (som faktisk ser ud til at få begge resultater)..
Avatar billede mollevp Nybegynder
16. august 2005 - 09:39 #7
ja - har lige testet det hvis jeg udskriver det jeg læser i første recv - er begge resultater der.. Jeg er virkelig lost her - hvordan kan det lade sig gøre??
Avatar billede arne_v Ekspert
16. august 2005 - 09:42 #8
nu kan jeg ikke lige gennemskue dit send og recv flow - hvorfor er du sikker på
at du først laver din anden send efter første recv ?
Avatar billede arne_v Ekspert
16. august 2005 - 09:43 #9
men ellers læs indtil du modtager \r\n, så er din kode noget mere robust
overfor sockets måde at virke på
Avatar billede mollevp Nybegynder
16. august 2005 - 09:52 #10
>> nu kan jeg ikke lige gennemskue dit send og recv flow - hvorfor er du sikker på
>> at du først laver din anden send efter første recv ?

Det er bare fordi det er sådan jeg sender det i koden.. Men det kan måske ske at det ikke nødvendigvis er sådan?

Koden med alt overflødig fjernet:

  strcpy(command,"session direct stats show");
  send_command(sd,peer,command);

  ... kode ...

  // Looping as long as there is something to read
  while((recv_status = recv(sd, buf+ix, sizeof(buf)-ix-1, 0)) > 0){
    ix = ix + recv_status;
  }

  ... kode ... 

  // Broadcast stream status - send request to switch device
  strcpy(command,"session bc stats show");
  send_command(sd, peer, command);
 
  ... kode ...

  // Looping as long as there is something to read
  while((recv_status = recv(sd, buf+ix, sizeof(buf)-ix-1, 0)) > 0){
    ix = ix + recv_status;

  }

I ovnestående kode bliver resultatet af:

  strcpy(command,"session bc stats show");
  send_command(sd, peer, command);

læst i første recv while løkke..
Avatar billede arne_v Ekspert
16. august 2005 - 10:06 #11
er du sikker på at det ikke er begge kommandoer som bliver læst i sidste løkke ?
Avatar billede mollevp Nybegynder
16. august 2005 - 10:19 #12
Ja, for jeg har lavet en printf på buf efter første read og efter anden.. og alt data bliver udskrevet i første..
Avatar billede mollevp Nybegynder
16. august 2005 - 11:09 #13
Arne, jeg har fundet problemet ... der skulle simpelthen et timedelay ind - mellem send_command og recv kaldene.. nu virker det fint.. Den var simpelthen kommet bagefter med svarne på vores forespørgsel..

Jeg kan dog ikke så godt lide sådan nogel time-delay løsninger.. kender du nogle andre muligheder..

At lave socket'en blocking har desværre ingen effekt - da der jo næsten altid kommer de 4 byte..
Avatar billede mollevp Nybegynder
17. august 2005 - 18:26 #14
Arne jeg takker for din hjælp - lig et svar :)
Mvh Morten
Avatar billede arne_v Ekspert
18. august 2005 - 15:35 #15
ok

selvom jeg stadig ikke er sikker på at jeg har forstået problematikken helt
Avatar billede mollevp Nybegynder
18. august 2005 - 15:47 #16
Problemet var tilsyneladende at vi sende forespørgslerne for hurtigt, switch-devicen nåede simplethen ikke at svare.. jeg kunne se det ved at ligge et lille time-delay ind mellen send_command og recv kaldene..

Jeg ville gerne undgå den slags manuelle time-delays, men har ikke fundet på noget endnu..
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