GNU/Linux >> Linux Esercitazione >  >> Linux

Controlla la connessione aperta o chiusa? (in C in Linux)

Uso send() invece write() che non gestisce alcun segnale :

bzero(buffer, MAX_SIZE_BUFFER);
n = read(sockfd, buffer, MAX_SIZE_BUFFER - 1);
printf("after read%d\n", n);
if (n <= 0)
{
    break;
}
n2 = send(newsockfd, buffer, n, MSG_NOSIGNAL);
if (n2 == -1)
{
    close(sockfd);
    close(newsockfd);
    return;
}
if (n2 != n)
{
    break;
}

La programmazione dei socket può essere piuttosto complicata, perché spesso non sai che si è verificato un errore se non molto tempo dopo.

Ad esempio, se la macchina su cui stai scrivendo si spegne in modo anomalo, la chiamata di scrittura potrebbe riuscire (poiché sei stato in grado di scrivere nei buffer interni del tuo sistema operativo), solo per fallire durante la chiamata di chiusura.

A meno che tu non abbia un modo a livello di applicazione per verificare che il socket sia attivo (ovvero, inviando un messaggio e richiedendo una risposta entro un certo periodo di tempo) non hai modo di saperlo. Se stai usando un protocollo standard, potrebbe già esistere qualcosa per gestire gli errori.

Quindi la risposta breve è che devi controllare i ritorni di errore praticamente da ogni chiamata che tocca il socket ( leggi, scrivi, chiudi, ecc ... ).


Il modo per verificare se puoi scrivere su un socket è, sorprendentemente, provare a scriverci sopra :-)

Se il socket è stato chiuso, otterrai un -1 codice di ritorno da write e puoi esaminare errno per vedere qual era il problema.

Se il socket è ancora valido ma al momento non puoi scrivere alcun dato, write restituirà 0. Il read call si comporta anch'essa in modo simile, restituendo -1 se c'è un problema.

Fondamentalmente, per write :

  • se ricevi indietro un -1 , si è verificato un problema e dovresti selezionare errno per vedere se è recuperabile o fatale.
  • Se ricevi un 0 , quindi non puoi scrivere nulla al momento (potrebbe essere un arretrato di rete o qualche altro problema ma sicuramente non (ancora) fatale).
  • Se ottieni un valore inferiore a quello che volevi, allora alcuni dei dati è stato inviato. Regola i tuoi puntatori in modo da poter provare a inviare il resto nel ciclo successivo. No assumere un valore di ritorno positivo significa che l'intero blocco è stato inviato.
  • Se ricevi lo stesso numero del numero di byte che hai provato a inviare, l'intero buffer è stato accettato per la consegna.
  • Se ricevi più di quanto hai chiesto di ricevere, invia un'e-mail agli sviluppatori del kernel con qualche commento aspro. Linus e altri lo adoreranno :-)

Aggiornamento: Come ha sottolineato caf nei commenti, ho dimenticato di prendere in considerazione la gestione del segnale. Devi ignorare il segnale di tubo rotto o write fallirà internamente alzando quel segnale.

Puoi farlo inserendo:

struct sigaction new_actn, old_actn;
new_actn.sa_handler = SIG_IGN;
sigemptyset (&new_actn.sa_mask);
new_actn.sa_flags = 0;
sigaction (SIGPIPE, &new_actn, &old_actn);

prima di iniziare a utilizzare le funzioni socket. Puoi quindi utilizzare:

sigaction (SIGPIPE, &old_actn, NULL);

per ripristinare la precedente gestione del segnale.


Linux
  1. Come controllare l'ascolto / aprire le porte con Netstat su Linux

  2. Controlla il limite FD aperto per un determinato processo in Linux

  3. appunti di linux leggi/scrivi in ​​C

  4. Come scrivere un driver di dispositivo a blocchi Linux in spazio utente?

  5. Controlla se la porta è aperta o chiusa su un server Linux?

Cosa sono i porti? Come controllare le porte aperte di Linux?

Come controllare le porte aperte in Linux

Come verificare che una porta sia aperta su un sistema Linux remoto

Come controllare tutte le porte aperte nel tuo sistema Linux

Come controllare le porte aperte in Linux?

Tutti i modi per verificare se una porta è aperta in Linux