[C] recv() non bloccante

Area di discussione libera.

Moderatore: Staff

Regole del forum
1) Rispettare le idee altrui.
2) Evitare le offese dirette.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

[C] recv() non bloccante

Messaggio da Dani »

In un programma (client) mi aspetto di ricevere da un server qualcosa tipo:

Codice: Seleziona tutto

stringa1\r\n
stringa2\r\n
stringaN\r\n
non conosco il numero di stringhe che saranno inviate, e dopo aver ricevuto l'ultima mi si blocca il programma. In pratica recv() continua ad aspettare altri dati, solo che non arriveranno mai :roll:
E' possibile mettere un timeout alla funzione ?

Avatar utente
gallows
Staff
Staff
Messaggi: 3471
Iscritto il: lun 20 set 2004, 0:00
Desktop: cwm
Distribuzione: OpenBSD
Località: ~/
Contatta:

Messaggio da gallows »

man 3 poll

Se hai qualche dubbio su come funziona ti faccio un esempio.

Avatar utente
mcosta
Linux 0.x
Linux 0.x
Messaggi: 54
Iscritto il: mar 15 giu 2004, 0:00
Nome Cognome: Massimo Costa
Slackware: 13.0
Kernel: 2.6.29.6
Desktop: KDE 4.2.4
Località: Marano (NA)

Messaggio da mcosta »

Le soluzioni sono 2:

1) Usi la select() a cui puoi impostare un timeout e poi usi recv() per scodare dal buffer

2) Imposti il socket in modalità non bloccante e controlli il risultato della recv() per accorgerti che non c'è nulla da leggere

Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

Messaggio da Dani »

Avevo trovato qualcosa sulla select() ma non capisco perchè il programma subito dopo il timeout va in segfault:

Codice: Seleziona tutto

...
	FD_ZERO (&read_set);
		
	while (1) 
	{
		FD_SET (sd, &read_set);
		timeout.tv_sec = 5;
		timeout.tv_usec = 0;	
		
		rval = select (sd + 1, &read_set, NULL, NULL, &timeout);
	
		if (rval < 0)
	 	_error ("select() call failed.");  /* uscita dal programma */
		else if (rval)
		{
			if ((read = recv (sd, buff, size, 0)) < 0)
	 		 _error ("...");  /* uscita dal programma */
	 	 
			buff[read] = 0;
			... /* qui altro codice per estrarre cio' che mi serve dai dati ricevuti */
			
		}
		else
		{
			printf ("\nTimeout occured.\n");
	 		break;
		}
	}
return 0;
Appena il programma arriva al return va in segfault...

Avatar utente
gallows
Staff
Staff
Messaggi: 3471
Iscritto il: lun 20 set 2004, 0:00
Desktop: cwm
Distribuzione: OpenBSD
Località: ~/
Contatta:

Messaggio da gallows »

Sicuro che non ottiene un SIGSEGV quando manipoli il buffer? Per analizzare ciò che avviene prova strace o meglio ancora gdb. Oppure allega (o linka se è lungo) l'intero programma e gli diamo un'occhiata.

EDIT: ad ogni modo, sembra che tu debba controllare un solo file descriptor, in questo caso, IMO, è più logico usare poll...

Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

Messaggio da Dani »

Si infatti, avevo fatto un po' di casino con i puntatori :x
Ho continuato ad usare la select() perchè ho trovato poca documentazione riguardo la poll()...Certo che queste funzioni sono alquanto criptiche (o sono io negato ?) :roll:

Avatar utente
gallows
Staff
Staff
Messaggi: 3471
Iscritto il: lun 20 set 2004, 0:00
Desktop: cwm
Distribuzione: OpenBSD
Località: ~/
Contatta:

Messaggio da gallows »

Guarda, poll è abbastanza semplice:

Codice: Seleziona tutto

/* ... */
#include <poll.h>

TcpData* tcp_recv(int fd)
{
   /* ... */
    struct pollfd pfd; /* struttura per UN fd da monitorare */

    pfd.fd     = fd; /* assegno il file descriptor del socket */
    pfd.events = POLLIN; /* mi aspetto eventi in entrata */

    for (;;) {

/*  primo argomento: puntatore alle strutture da monitorare, in questo caso è una sola
 *  secondo: numero di strutture
 *  terzo: timeout in msec
 */
        int res = poll(&pfd, 1, TIMEOUT);

        if (!res) {
            /* time out */
        }
        else if (res < 0) {
           /* errore */
        }
        else {
            /* lettura del socket */
        }
    }

    return data;
}

Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

Messaggio da Dani »

Capito, grazie mille !

Rispondi