Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    problema read e write su socket

    Salve a tutti... sto facendo qualche esercizio sui socket in linux e mi sono imbattuto in questo problemino che non riesco a capire... quindi chiedo se vi è mai capitato e come avere risolto.

    Il problema è questo :
    Sia sul programma server( è iterativo) che sul client la connessione viene creata normalmente e senza problemi.
    Il problema riguarda il trasferimento dei dati. Il programma server esegue il comando ls redirigendo l'output del comando su un file. Dopodiché legge dal file e scrive sul socket col seguente codice
    codice:
    while (read(file_descriptor,buf,1)>0) {
         write(sock,buf,1);
    }
    close(sock)
    Questo codice funziona perfettamente, infatti i dati vengono correttamente inviati al client per poi passare ad accettare la connessione successiva.

    Il client invece usa il seguente codice per leggere dal socket e stampare sullo standard output
    codice:
    while (read(sock,buf,1)>0) {
         write(STDOUT_FILENO,buf,1);
    }
    close(sock)
    Il client dopo aver ricevuto tutti i dati provenienti dal socket (li stampa correttamente a video) si blocca sulla read, cercando di leggere ancora dal socket. Ovviamente siccome il socket è vuoto non legge niente e si blocca il programma.
    Avete qualche soluzione al problema?

    grazie in anticipo... ciao ciao

  2. #2
    Hai due possibilità:
    - usare socket non bloccanti (ma la sconsiglio perchè poco efficenti per attendere dei dati);
    - chiudere il socket una volta terminato l'invio con una shutdown(sock, 2), che chiude la parte di invio della socket prima di fare la close; la read dovrebbe sbloccarsi con un errore (ma non sempre lo fa ) ;
    - usare la select
    codice:
      fd_set socket_set;
      FD_ZERO(&socket_set);
      struct timeval tv;
    
      FD_SET(sock, &socket_set);
    
      tv.tv_sec = time_out;
      tv.tv_usec = 0;
    
      select(sock + 1, NULL, &socket_set, NULL, &tv);
    stai attendo perchè la socket è portabile ma ha piccole differenze nei parametri; quello che ho scritto è per linux, per windows al posto di sock + 1 metti 1.
    - inviare un byte a zero per indicare al client che il server ha terminato (è la soluzione che preferisco) l'invio, così non stai ad aspettare.

    Inoltre invierei e leggerei più bytes alla volta, inviare 1 solo byte è inefficente.

  3. #3
    Innanzitutto ti ringrazio per l'attenzione, poi ti vorrei fare due domande

    1. A che serve quella funzione select? O meglio che cosa fa?

    2. Per l'invio di un byte 0 intendi un "\0" ? E in questo caso il client dovrà controllare se il byte ricevuto è \0? E facendo cosi non sono obbligato a leggere comunque un byte alla volta?

  4. #4
    - la select si mette in attesa di un evento su un socket (se sei su linux prova a fare un man select); puoi scegliere di attendere un evento di scrittura (cioè se puoi scrivere sul socket); un evento in lettura (cioè se puoi leggere dal socket perchè ci sono dati non letti); altri eventi (come l'arrivo di dati Out of Band etc.); esce perchè scade il timeout oppure perchè si è verificato uno degli eventi; a quel punto puoi indagare su quale socket l'evento si è verificato ma nel tuo caso usi la select su un solo socket su una sola categoria di eventi e quindi il controllo è ridondante (se leggi la man page ti da' più informazioni )
    - non è vero che devi per forza leggere un byte alla volta....puoi leggere che so 512 byte e verificare se nel buffer è presente il byte 0 nei dati effettivamente letti (la read non termina il buffer di lettura con uno zero). Quindi se fai una sz = read(sock, buff, 512), e poi cerchi nei primi sz bytes di buff se c'è uno zero allora sai che l'invio è terminato (sempre che non invii il buffer come stringhe separate); comunque puoi cercare anche un altro valore che so 0xFF, l'importante è che il byte che cerchi non faccia parte dei dati utili; inoltre non devi cercare il byte tra tutti quelli letti ma solo vedere se l'ultimo byte letto dalla read è quel valore (un buffer lungo potrebbe essere spezzato per frammentazione anche se con 512 non corri questo rischio).


  5. #5
    Quindi come dici tu dovrei fare una cosa del genere :
    codice:
    bytes=read(sock,buffer,512);
    if (buffer[bytes]=='\0') "interrompo il ciclo di lettura"
    giusto?

    Poi, scusa forse questa è una domanda un po' stupida, ma come si scrivono i C questi valori tipo 0xFF ?

  6. #6
    No, mettere buffer[bytes - 1] perchè gli array in C iniziano da zero, metterei anche un controllo sul fatto che la read abbia letto qualcosa (se no fa del casino incredibile).
    Per il fatto del 0xFF, anche se buffer è un'array di char, non devi per forza passagli un char con le '' (puoi usando le sequenze di escape), puoi anche passare direttamente il valore:
    codice:
    buffer[bytes] == 0xFF
    Di più non puoi perchè il char è un 8bit.

  7. #7
    post doppio

  8. #8
    Originariamente inviato da fastcoder
    No, mettere buffer[bytes - 1] perchè gli array in C iniziano da zero
    Ehm si, questa è stata distrazione

    Cmq Grazie mille ora lo provo e vediamo se funziona.

    Scusa forse questa è un'altra domanda stupida, ma questa è una sintassi non l'ho mai usata.
    in 0xFF, FF indica il valore esadecimale corrispondente al valore ascii del carattere che mi serve giusto? Cioè 0xFF sta a indicare il carattere di codice 255 giusto?

  9. #9
    Esattamente

  10. #10
    Grazie mille mi sei stato di grande aiuto

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.