View Full Version : [C] socket non bloccante
bouncey2k
04-08-2008, 17:52
Ho scoperto da poco che il socket di default (almeno sotto unix) è bloccante, sto cercando di risolvere il problema con
fcntl(sd,F_SETFL,O_NONBLOCK);
senza risultati positivi.
Senza stare a postare tutto il codice vi riassumo il tutto:
creo il socket sd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
lo rendo non bloccante con l'istruzione sopracitata e mi connetto ad un server.
Dopodiché invio e ricevo un messaggio con send() e recv(). Tutto liscio: mando e ricevo il messaggio di risposta dal server.
A questo punto, avendo reso il socket non bloccante, dovrei essere in grado di mandare e ricevere altri messaggi, invece nulla.
Al secondo recv() che faccio, l'int di recv() mi restituisce 0, segno che la connessione dall'altro lato (server) è chiusa.
Un aiutino? :muro:
PS: programmo sotto linux
Slayer86
04-08-2008, 18:40
Ho scoperto da poco che il socket di default (almeno sotto unix) è bloccante, sto cercando di risolvere il problema con
fcntl(sd,F_SETFL,O_NONBLOCK);
senza risultati positivi.
Senza stare a postare tutto il codice vi riassumo il tutto:
creo il socket sd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
lo rendo non bloccante con l'istruzione sopracitata e mi connetto ad un server.
Dopodiché invio e ricevo un messaggio con send() e recv(). Tutto liscio: mando e ricevo il messaggio di risposta dal server.
A questo punto, avendo reso il socket non bloccante, dovrei essere in grado di mandare e ricevere altri messaggi, invece nulla.
Al secondo recv() che faccio, l'int di recv() mi restituisce 0, segno che la connessione dall'altro lato (server) è chiusa.
Un aiutino? :muro:
PS: programmo sotto linux
Credo, ma non sono sicuro, che il socket non bloccante si riferisca al fatto che la chiamata effettuata sopra di esso non aspetta risposta per terminare ma ritorna appunto 1 se ha successo 0 se falliscie, evitando quindi di bloccare il processo che la esegue.
Nel tuo caso è infatti così, la seconda chiamata ritorna 0 mentre la prima viene eseguita, questo perchè la porta associata al socket è occupata!!!
Spero di essere stato chiaro...
bouncey2k
04-08-2008, 18:51
Parli della porta del client o del server? Come è possibile che sia occupata se ho usato solo due comandi send() e recv()?
La caratteristica "non bloccante" si riferisce proprio alla recv. La recv in un socket normale se non arrivano dati resta in attesa dell'arrivo. In un socket non bloccante la recv ritorna subito 0 se non ci sono dati pronti per la lettura.
Slayer86
04-08-2008, 21:32
La caratteristica "non bloccante" si riferisce proprio alla recv. La recv in un socket normale se non arrivano dati resta in attesa dell'arrivo. In un socket non bloccante la recv ritorna subito 0 se non ci sono dati pronti per la lettura.
Giustooo cionci ha sempre ragione!
Ho detto in parte una castroneria... se avesse letto il mio prof di reti di calcolatori mi toglieva il voto e mi costringeva a ridare l'esame!!!
bouncey2k
04-08-2008, 22:05
La caratteristica "non bloccante" si riferisce proprio alla recv. La recv in un socket normale se non arrivano dati resta in attesa dell'arrivo. In un socket non bloccante la recv ritorna subito 0 se non ci sono dati pronti per la lettura.
Scusa ma non è l'inverso? In un socket normale (bloccante) se la recv() non riceve dati la comunicazione si chiude. Sennò che senso avrebbe fare un socket non-bloccante?
Ad ogni modo come faccio a fare in modo che il mio client usi più recv() durante la stessa connessione senza che questa venga chiusa?
Slayer86
04-08-2008, 22:26
Scusa ma non è l'inverso? In un socket normale (bloccante) se la recv() non riceve dati la comunicazione si chiude. Sennò che senso avrebbe fare un socket non-bloccante?
Ad ogni modo come faccio a fare in modo che il mio client usi più recv() durante la stessa connessione senza che questa venga chiusa?
questo è ciò che riportano le slide su cui a suo tempo ho studiato ti serve per capire cosa significa bloccante:
Letture/scritture bloccanti
Le operazioni di lettura e scrittura che abbiamo definito sono bloccanti:
• Per una operazione di lettura cio' significa che
• Se non ci sono dati disponibili nel buffer di ricezione del socket al
momento dell'invocazione dell'operazione, il processo chiamante
si blocca in attesa che dei dati diventino disponibili.
• Quando i dati diventano disponibili la system call termina, e i dati
a quel punto disponibili vengono ritornati al chiamante.
• Per una operazione di scrittura cio' significa che
• Se nel buffer di trasmissione del socket non c'e' spazio di
memoria per ospitare i dati (ad es. perche' la rete e' piu' lenta a
consumare dati di quanto sia il processo a produrli), il processo
si blocca in attesa che tale spazio diventi disponibile.
• Quando c'e' spazio disponibile l'esecuzione della system call
riprende: tutti i dati che possono essere copiati nel socket
(perche' c'e' abbastanza spazio) lo sono, e l'operazione termina.
se un'operazione non è bloccante significa che il processo che la esegue non si ferma ad aspettare il risultato... nel caso della recv() non bloccante se non c'è scritto nulla sul socket la recv() non si ferma ad aspettare ma ti avvisa che non ha letto nulla...
non capisco cosa intendi dire con usare più recv()... così su due piedi mi pare che a te serva un socket bloccante come nella maggior parte dei casi!
ilsensine
05-08-2008, 08:37
La caratteristica "non bloccante" si riferisce proprio alla recv. La recv in un socket normale se non arrivano dati resta in attesa dell'arrivo. In un socket non bloccante la recv ritorna subito 0 se non ci sono dati pronti per la lettura.
No ritorna -1 con errno=EAGAIN. Il problema è da un'altra parte...
ilsensine
05-08-2008, 08:39
creo il socket sd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
lo rendo non bloccante con l'istruzione sopracitata e mi connetto ad un server.
Stai attento che se rendi il socket non bloccante prima della connect, la connect stessa è non bloccante.
bouncey2k
05-08-2008, 13:52
non capisco cosa intendi dire con usare più recv()... così su due piedi mi pare che a te serva un socket bloccante come nella maggior parte dei casi!
Per usare più recv() intendo il seguente codice:
CLIENT
send(arg) --> server
recv(arg) <-- server
send(arg2) --> server
recv(arg2) <-- server
Cioè ad ogni messaggio che mando al server, quello mi risponde, e i messaggi vengono mandati uno dopo l'altro, botta e risposta.
Se il socket è BLOCCANTE il primo recv() lo ricevo e il secondo recv() mi restituisce 0, connessione interrotta.
Se metto il socket NON BLOCCANTE (anche dopo la connect()) mi restituisce 0 direttamente alla prima recv().
Slayer86
05-08-2008, 14:13
Per usare più recv() intendo il seguente codice:
CLIENT
send(arg) --> server
recv(arg) <-- server
send(arg2) --> server
recv(arg2) <-- server
Cioè ad ogni messaggio che mando al server, quello mi risponde, e i messaggi vengono mandati uno dopo l'altro, botta e risposta.
Se il socket è BLOCCANTE il primo recv() lo ricevo e il secondo recv() mi restituisce 0, connessione interrotta.
Se metto il socket NON BLOCCANTE (anche dopo la connect()) mi restituisce 0 direttamente alla prima recv().
Bhe guarda secondo me il socket deve essere bloccante per quello che ti serve...
tu fai la send e poi subito una recv() in modo che il client si blocca ad aspettare che arrivi la risposta del server...
Poi tutto dipende da come è fatto il server... sei sicuro che gestisca per bene le richieste che gli arrivano e non si chiuda dopo una sola risposta?
bouncey2k
05-08-2008, 15:59
Allora ho fatto ancora quale prova.
Non ho impostato particolari caratteristiche al socket, percui di defaul è bloccante.
Il server non l'ho fatto io, è un server per chat ed usa un protocollo proprietario, ad ogni modo conosco il protocollo e le prime istruzioni sono varie recv() e send(), cioè riceve il messaggio dal client e mi risponde se è OK o no per circa 3-4 volte.
Mando un send() al server e ricevo con recv() la risposta, tutto ok.
Mando un secondo send() al server ricevo una risposta vuota, analizzo l'int della recv() ed è 0.
Per curiosità decido di sniffare il traffico con wireshark per vedere che succede.
Come riesco a notare mando la prima send() correttamente e ricevo la recv() correttamente.
Mando correttamente anche la seconda send(), ma quando dovrei ricevere la seconda recv() ecco che vedo un bel [FIN, ACK] mandato dal server ed un altro bel [FIN, ACK] mandato dal mio client come risposta.
:muro: :muro: :muro:
Slayer86
05-08-2008, 17:15
Allora ho fatto ancora quale prova.
Non ho impostato particolari caratteristiche al socket, percui di defaul è bloccante.
Il server non l'ho fatto io, è un server per chat ed usa un protocollo proprietario, ad ogni modo conosco il protocollo e le prime istruzioni sono varie recv() e send(), cioè riceve il messaggio dal client e mi risponde se è OK o no per circa 3-4 volte.
Mando un send() al server e ricevo con recv() la risposta, tutto ok.
Mando un secondo send() al server ricevo una risposta vuota, analizzo l'int della recv() ed è 0.
Per curiosità decido di sniffare il traffico con wireshark per vedere che succede.
Come riesco a notare mando la prima send() correttamente e ricevo la recv() correttamente.
Mando correttamente anche la seconda send(), ma quando dovrei ricevere la seconda recv() ecco che vedo un bel [FIN, ACK] mandato dal server ed un altro bel [FIN, ACK] mandato dal mio client come risposta.
:muro: :muro: :muro:
Secondo me o sbagli qualche cosa con il protocollo oppure è fatto male il server!
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.