Pagina 1 di 1

[C socket] aiuto sulla sincronizzazione

Inviato: venerdì 12 giugno 2015, 19:21
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);
    }

Re: [C socket] aiuto sulla sincronizzazione

Inviato: venerdì 12 giugno 2015, 20:05
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);

Re: [C socket] aiuto sulla sincronizzazione

Inviato: lunedì 15 giugno 2015, 20:45
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

Re: [C socket] aiuto sulla sincronizzazione

Inviato: lunedì 15 giugno 2015, 23:01
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?

Re: [C socket] aiuto sulla sincronizzazione

Inviato: lunedì 15 giugno 2015, 23:20
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.

Re: [C socket] aiuto sulla sincronizzazione

Inviato: martedì 16 giugno 2015, 0:03
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.

Re: [C socket] aiuto sulla sincronizzazione

Inviato: martedì 16 giugno 2015, 23:17
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

Re: [C socket] aiuto sulla sincronizzazione

Inviato: mercoledì 17 giugno 2015, 1:51
da SuperStep
quoto il corriere espresso.

Re: [C socket] aiuto sulla sincronizzazione

Inviato: mercoledì 17 giugno 2015, 4:32
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.

Re: [C socket] aiuto sulla sincronizzazione

Inviato: mercoledì 17 giugno 2015, 19:25
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. 😉

Re: [C socket] aiuto sulla sincronizzazione

Inviato: mercoledì 17 giugno 2015, 20:47
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.

Re: [C socket] aiuto sulla sincronizzazione

Inviato: mercoledì 17 giugno 2015, 21:18
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!!!

Re: [C socket] aiuto sulla sincronizzazione

Inviato: giovedì 18 giugno 2015, 7:54
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