[C socket] aiuto sulla sincronizzazione

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Avatar utente
errullaiolo
Prode Principiante
Messaggi: 185
Iscrizione: giovedì 17 gennaio 2013, 14:09
Distribuzione: Ubuntu 14.04.2 LTS
Sesso: Maschile

[C socket] aiuto sulla sincronizzazione

Messaggio da errullaiolo »

Come posso avere la certezza che le 3 operazioni siano avvenute in maniera ordinata e siano terminate con successo?
Inoltre il printf del server me lo fa in ritardo quando si connette il client successivo. A cosa è dovuto?


---CLIENT---

Codice: Seleziona tutto

 send(sockfd, com.cmd, 125, 0);
 send(sockfd, com.val1, 125, 0);
 send(sockfd, com.val2, 125, 0);
---SERVER---

Codice: Seleziona tutto

 recv(new_fd, com.cmd, 125, 0);
 recv(new_fd, com.val1, 125, 0);
 recv(new_fd, com.val2, 125, 0);

 if(strcmp(com.cmd,"CMP")==0)
    {
      printf("%s %s",com.val1, com.val2);
    }
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
errullaiolo
Prode Principiante
Messaggi: 185
Iscrizione: giovedì 17 gennaio 2013, 14:09
Distribuzione: Ubuntu 14.04.2 LTS
Sesso: Maschile

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da errullaiolo »

Funziona a intermittenza...


---SERVER accept ----

Codice: Seleziona tutto

 bzero(&com, sizeof(com));
  recv(new_fd, com.cmd, 125, 0);
  recv(new_fd, com.val1, 125, 0);
  recv(new_fd, com.val2, 125, 0);
  //printf("%s\n",com.cmd);

  /*  CMP  */
  if(strcmp(com.cmd,"CMP")==0)
    {
      n = strcmp(com.val1,com.val2);
      if(!n) printf("Le stringe %s e %s sono identiche\n", com.val1,com.val2); 
      else printf("Le stringe %s e %s non sono identiche\n", com.val1,com.val2);
    }

 /*  DIV  */
  else if(strcmp(com.cmd,"DIV")==0)
    {
      printf("%d\n", atoi(com.val1)/atoi(com.val2));
    }

 close(new_fd);
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
cortinico
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 477
Iscrizione: venerdì 15 maggio 2015, 16:49
Desktop: Unity
Distribuzione: Ubuntu 15.04 amd64
Sesso: Maschile
Località: Pisa
Contatti:

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da cortinico »

errullaiolo [url=http://forum.ubuntu-it.org/viewtopic.php?p=4768186#p4768186][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:Come posso avere la certezza che le 3 operazioni siano avvenute in maniera ordinata e siano terminate con successo?
Inoltre il printf del server me lo fa in ritardo quando si connette il client successivo. A cosa è dovuto?


---CLIENT---

Codice: Seleziona tutto

 send(sockfd, com.cmd, 125, 0);
 send(sockfd, com.val1, 125, 0);
 send(sockfd, com.val2, 125, 0);
---SERVER---

Codice: Seleziona tutto

 recv(new_fd, com.cmd, 125, 0);
 recv(new_fd, com.val1, 125, 0);
 recv(new_fd, com.val2, 125, 0);

 if(strcmp(com.cmd,"CMP")==0)
    {
      printf("%s %s",com.val1, com.val2);
    }
Tieni di conto che le printf e le varie funzioni di libreria stdio.h sono generalmente bufferizzate. Questo vuol dire che la scrittura su stdout non e' atomica con l'invocazione della funzione. Le alternative sono 2:

1) Usi una writer su stdout
2) Chiami una fflush(stdout) subito dopo la printf
"Look wide, and even when you think you are looking wide – look wider still!"
http://ncorti.com
Avatar utente
errullaiolo
Prode Principiante
Messaggi: 185
Iscrizione: giovedì 17 gennaio 2013, 14:09
Distribuzione: Ubuntu 14.04.2 LTS
Sesso: Maschile

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da errullaiolo »

Quindi una printf essendo bufferizzata, svuota il buffer quando ne ha voglia o tramite una stimolazione con fflush??
Ma la definizione di bufferizzata sarebbe che la funzione riesce subito a fornire il dato? Ha comunque alle spalle una funzione non bufferizzata?
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da SuperStep »

potresti anche settare la bufferizzazione della printf per fare in modo che funzioni "_come_" la write

Codice: Seleziona tutto

setbuf(stdout, NULL);
[EDIT]
per rispondere alla tua domanda, la printf scarica il buffer su stdout quando il buffer utilizzato e' pieno oppure quando incontra il carattere nuova linea ("\n") (comportamento di default).
e' possibile inoltre cambiare il tipo di bufferizzazione (disponibili: non_buffered, line_buffered, fully_buffered) e il buffer sul quale scaricare/prelevare l'output/input.

il motivo per cui questa cosa e' adoperata e' quella di avere un risparmio in termini di lettura/scrittura sul disco.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da vbextreme »

la send/recv su socket tcp non garantiscono il reale invio del dato in un colpo solo.
pertanto se si cerca di inviare anche solo un intero può succedere di inviare due byte e la send restituirà 2 e bisognerà inviare i sucessivi due caratteri, stesso discorso sulla recv che potrebbe ricevere uno e poi tre byte o in qualsiasi altra sequenza come potrebbe benissimo riceverli tutti e 4 in un colpo solo.
Gli unix socket invece garantiscono l'atomicita fino a 4096byte.
Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
errullaiolo
Prode Principiante
Messaggi: 185
Iscrizione: giovedì 17 gennaio 2013, 14:09
Distribuzione: Ubuntu 14.04.2 LTS
Sesso: Maschile

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da errullaiolo »

Potrebbe essere gestita con una serie di sleep dopo un pò di prove. Ma mi sembra troppo arcaica come soluzione.
Oppure metto in loop ogni ricezione e spedizione , le quali attendono delle signal per continuare . In questo caso ridondo nello sfruttare la rete per mandare le signal.
Oppure corriere espresso Bartolini :D
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da SuperStep »

quoto il corriere espresso.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da vbextreme »

Sicuramente Bartonili è più veloce e preciso del tuo codice.....
L'invio dei dati deve essere implementato così:

Codice: Seleziona tutto

int safesend(int sck, void* v, size_t s)
{
    unsigned char* d = v;
    size_t ss;
    while ( s )
    {
        if ( (ss = send(sck,d,s,0)) <= 0 ) return -1;
        s -= ss;
        d += ss;
    }
    return 0;
}
e la ricezione:

Codice: Seleziona tutto

int saferecv(int sck, void* v, size_t s)
{
    unsigned char* d = v;
    size_t ss;
    while ( s )
    {
        if ( (ss = recv(sck,d,s,0)) <= 0 ) return -1;
        s -= ss;
        d += ss;
    }
    return 0;
}
o suo sostituto magari scritto da un computer invece che un telefono.

Naturalmente andando in easyframework->easysocket->easysocket.c avresti visto le due funzioni _sck_read() e _sck_write() usate internamente per spedire e ricreare il dato correttamente.
Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
errullaiolo
Prode Principiante
Messaggi: 185
Iscrizione: giovedì 17 gennaio 2013, 14:09
Distribuzione: Ubuntu 14.04.2 LTS
Sesso: Maschile

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da errullaiolo »

Ok sulla safe send e recv ci sto. Ma il mio inghippo penso dicasi programmazione concorrente. Socket client e server utilizzano (poco dignitosamente nel mio !codice) lo stesso canale in parallelo per comunicare. Devo quindi sincronizzare le mie operazioni di send e recv. Ció puó avvenire come una sincronizzazione interprocesso o nella rete entrano in gioco altri meccanismi?


Con 10 yottabyte, Bartolini evita la wait. 😉
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da vbextreme »

la safe serve solo per assicurare il corretto invio/ricezione dei dati.
Non capisco dove sia la programmazione concorrente hai un processo server e uno client che comunicano tramite socket, ti serve un protocollo!
Pertanto definisci prima tale protocollo e poi procedi nel gestire la comunicazione ed a implementare meccanismi di sincronizzazione quando e se necessario.

IPC penso si riferisca solo in locale.
Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
errullaiolo
Prode Principiante
Messaggi: 185
Iscrizione: giovedì 17 gennaio 2013, 14:09
Distribuzione: Ubuntu 14.04.2 LTS
Sesso: Maschile

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da errullaiolo »

Si chiedo scusa in effetti i file descrittori delle socket sono due.
Ecco il senso di avere un protocollo... Mi sento un imbecille.
Precisamente un protocollo soltanto a livello applicativo che dia il via a certe operazioni o ne metta in attesa altre o generi errori per sincronizzare parsimoniosamente le primitive delle socket.
Anche i protocolli devono utilizzare le primitive delle socket e quindi vanno temporizzate? O chi controlla il controllore?
Questi dubbi mi porteranno alla morte!!!
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [C socket] aiuto sulla sincronizzazione

Messaggio da vbextreme »

il protocollo lo decidi tu, la prima cosa da fare è prendere carta e penna.
Inizia a scrivere cosa deve fare la tua applicazione ad esempio:

Codice: Seleziona tutto

SERVER:
-riceve dei messaggi lunghi al massimo 80 caratteri terminati con \0 e li visualizza a schermo.
-supporta al massimo un client alla volta.
-usa la porta 999.

CLIENT:
-invia dei messaggi lunghi al massimo 80 caratteri terminati con \0 presi da input utente.
-si connette solo ad un server alla volta.
-l'utente seleziona l'ip ma la porta è fissa a 999
Ora prendi altri due fogli, su uno scrivi in alto e centrale SERVER e sull'altro CLIENT, li affianchi.

Codice: Seleziona tutto

SERVER             CLIENT
listen 999<--------connect xxx.xxx.xxx.xxx:999
->wait message     wait user message<-
| saferecv(msg)<---send message      |
| view message     loop---------------
--loop
ecco il piu semplice dei protocolli.
Poi lo disegni come piu ti piace e piu sei dettagliato e migliora sarà la tua applicazione
Easy framework per il linguaggio C.
vbextreme hack your life
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 4 ospiti