Torna indietro   Hardware Upgrade Forum > Software > Programmazione

DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker
DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker
Analizziamo nel dettaglio DJI RS 5, l'ultimo arrivato della famiglia Ronin progettato per videomaker solisti e piccoli studi. Tra tracciamento intelligente migliorato e ricarica ultra rapida, scopriamo come questo gimbal eleva la qualità delle produzioni.
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming
AMD Ryzen 7 9850X3D è la nuova CPU gaming di riferimento grazie alla 3D V-Cache di seconda generazione e frequenze fino a 5,6 GHz. Nei test offre prestazioni superiori a 9800X3D e 7800X3D, confermando la leadership AMD nel gaming su PC.
Le soluzioni FSP per il 2026: potenza e IA al centro
Le soluzioni FSP per il 2026: potenza e IA al centro
In occasione del Tech Tour 2025 della European Hardware Association abbiamo incontrato a Taiwan FSP, azienda impegnata nella produzione di alimentatori, chassis e soluzioni di raffreddamento tanto per clienti OEM come a proprio marchio. Potenze sempre più elevate negli alimentatori per far fronte alle necessità delle elaborazioni di intelligenza artificiale.
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 08-12-2016, 21:06   #1
stefanoxjx
Senior Member
 
L'Avatar di stefanoxjx
 
Iscritto dal: Jul 2002
Città: Padova
Messaggi: 4245
[c++]Come capire se un socket è attivo...

Ciao a tutti, sto giocando un po' con i socket per imparare qualcosa di nuovo.
Facendo un po' di prove sono riuscito a mettere su un pseudo server telnet, però come sempre c'è un problema che non riesco a risolvere
Allora, il server che ho scritto, accetta due comandi, ciao e quit.
Ovviamente con ciao risponde saluti e con quit chiude la connessione.
Fin qui non ci sono problemi, nel senso che con quit richiamo close(socket) e imposto socket a -1, così il server sa che dovrà chiamare nuovamente accept() per reimpostare un socket valido.
Il problema però lo trovo quando a chiudere la connessione è il client, vuoi perchè il pc remoto si spegne, perchè l'utente chiude brutalmente il programma, perchè prende fuoco il cavo di rete ecc.
In questo caso, non riesco a trovare un modo per capire se la connessione è ancora attiva oppure no.
Nel caso il client chiuda la connessione, il socket del server rimane invariato.
Ho provato varie soluzioni anche proposte nei vari forum che ho visto facendo ricerche in merito, ma sembra che nemmeno una funzioni
L'ultima che ho provato per dirne una è questa:
Codice:
    int error;
    socklen_t errCodeSize = sizeof(error);

    getsockopt(clientSocket, SOL_SOCKET, SO_ERROR, &error, &errCodeSize);
ma anche in questo caso la variabile error rimane invariata in caso di caduta della connessione con il client.

Inutile che chieda se esiste una soluzione, sono sicuro che c'è, ma a questo punto chiedo aiuto ai più esperti.
Grazie.

Stefano
stefanoxjx è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 12:23   #2
71106
Bannato
 
Iscritto dal: Nov 2014
Messaggi: 292
Usa setsockopt con SO_KEEPALIVE.

Ovviamente il SIGPIPE non arrivera' immediatamente ma questo e' il meglio che si possa fare perche' ovviamente non esiste modo di distinguere un silenzio del client dovuto al non invio di dati da un silenzio dovuto alla caduta della connessione.
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 12:27   #3
71106
Bannato
 
Iscritto dal: Nov 2014
Messaggi: 292
BTW, se il client chiude la connessione in maniera regolare il server se ne dovrebbe accorgere, se cosi' non e' hai sbagliato qualcosa.

Il sistema operativo dell'host su cui gira il client dovrebbe chiudere le connessioni TCP in maniera regolare persino quando il processo viene killato malamente. Il keepalive serve solo a gestire casi come "mia sorella e' inciampata sul cavo".
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 15:09   #4
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
In realta' il server dovrebbe accorgersi immediatamente anche se la socket e' chiusa in maniera irregolare (per esempio se il client e' killato) se e' in attesa su una read.

C'e' qualcosa di strano nella descrizione che hai fatto del problema: hai detto che in caso di chiusura il server potra' passare a fare una nuova accept().
In realta' le cose sono scorrelate e normalmente un server e' continuamente in attesa di nuove connessioni: hai fatto per caso un server che puo' servire un solo client alla volta?
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 16:17   #5
stefanoxjx
Senior Member
 
L'Avatar di stefanoxjx
 
Iscritto dal: Jul 2002
Città: Padova
Messaggi: 4245
Alllora... per iniziare ringrazio entrambi per l'attenzione
Ora, venendo al problema su cui ho continuato a lavorare e per il quale non ho trovato ancora una soluzione:
@71106: A dire il vero non sono ancora arrivato a far chiudere la connessione regolarmente al client, al momento stavo lavorando solo sul server e come client sto usando telnet.
Se invio il comando quit al server è il server che chiude la connessione, ma come dicevo in questo caso per fare in modo che poi il server mi becchi una nuova connessione devo rilanciare un nuovo accept(), altrimenti poi riesco a collegarmi ancora con telnet senza errori, ma sembra che il server non riceva più nulla.

@sottovento:
Codice:
C'e' qualcosa di strano nella descrizione che hai fatto del problema: hai detto che in caso di chiusura il server potra' passare a fare una nuova accept().
In realta' le cose sono scorrelate e normalmente un server e' continuamente in attesa di nuove connessioni: hai fatto per caso un server che puo' servire un solo client alla volta?
Su listen() ho specificato 3 connessioni anche se in realtà una volta messo a punto tutto volevo portare il valore a 1.

Siccome sto studiando anche il C++ e sto cercando di capire anche questo "nuovo" linguaggio, la voglia di studiare i socket mi è venuta per prendere due piccioni con una fava.
Cioè stavo cercando di scrivere una classe per gestire i socket.
Quindi mi sa che faccio prima a postare il codice che forse capite meglio voi e anche io

servertelnet.cpp
Codice:
#include <fcntl.h>
#include <signal.h>
#include "servertelnet.h"

ServerTelnet::ServerTelnet() {}

int8_t ServerTelnet::createSocket(uint16_t port)
{
    //Salva la porta in uso sulla variabile della classe
    tcpPort=port;

    //Crea il descrittore del socket
    socketDescriptor = socket(AF_INET , SOCK_STREAM , 0);
    if (socketDescriptor == -1) return ERRSOCKET;

    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(tcpPort);

    //Bind
    if( bind(socketDescriptor,(struct sockaddr *)&server , sizeof(server)) < 0) return ERRBIND;

    //Listen
    listen(socketDescriptor , 3);


    acceptConnection();
    /*int32_t c = sizeof(struct sockaddr_in);

    //accept connection from an incoming client
    clientSocket = accept(socketDescriptor, (struct sockaddr *)&client, (socklen_t*)&c);
    if (clientSocket < 0) return ERRCLIENTSOCKET;*/

    return(0);
}

//Chiude il socket
void ServerTelnet::closeSocket(void)
{
    close(clientSocket);
    clientSocket=-1;
}

//Attende dati dal client e li restituisce come argomento string
string ServerTelnet::receiveData(void)
{
    char clientMessage[BUFFERSIZE];
    int16_t readSize;

    //cout << clientSocket << endl;
    //perror("boh");
    //cout << errno << endl;

    checkConn();

    if(clientSocket==-1) return("");

    //Legge i dati
    readSize=recv(clientSocket,clientMessage, BUFFERSIZE , 0);

    //Termina il buffer togliend gli ultimi due caratteri \r\n
    if(readSize > 2) clientMessage[readSize-2]=0;
    else clientMessage[0]=0;

    //Ritorna il   dato letto convertito in string
    return(string(clientMessage));
}

//Invia dati al client e ritorna il numero di byte inviati oppure < 0 se errore
int8_t ServerTelnet::sendData(string pkg)
{
    if(clientSocket==-1) return(-1);
    else return(write(clientSocket, pkg.c_str(), pkg.length()));
}

//Ritorna la porta TCP con cui è stato aperto il socket
int16_t ServerTelnet::getPort(void)
{
    return tcpPort;
}

//Ritorna il descrittore del socket
int64_t ServerTelnet::getSocketDescriptor(void)
{
    return socketDescriptor;
}

//Ritorna il socket aperto dal client
int64_t ServerTelnet::getClientSocket(void)
{
    return clientSocket;
}

//Crea un socket che può accettare connessioni
int8_t ServerTelnet::acceptConnection(void)
{
    int32_t c = sizeof(struct sockaddr_in);
    clientSocket = accept(socketDescriptor, (struct sockaddr *)&client, (socklen_t*)&c);
    if (clientSocket < 0) return ERRCLIENTSOCKET;

    return(0);
}

int8_t ServerTelnet::checkConn(void)
{
    char buf[10];
    int i=0;
    i=write(clientSocket, "", 1);


//          i=recv(clientSocket, &buf, 1, MSG_PEEK | MSG_DONTWAIT);
    //cout << i << endl;
/*
    cout << "EAGAIN" << EAGAIN << endl;
    cout << "EBADF" << EBADF << endl;
    cout << "ENOTCONN" << ENOTCONN << endl;
    cout << errno << endl;*/

    int err = 0;
    socklen_t size = sizeof (err);
    int check = getsockopt (clientSocket, SOL_SOCKET, SO_ERROR, &err, &size);
    if (check != 0)
    {
       cout << "Errore socket" <<  endl;
    }
    //cout << check << endl;
    return(check);
}
Il metodo checkConn è un po' pasticciato perchè ci sono varie prove che stavo facendo oltre a dell'altro codice che in tutte le varie prove ho buttato via perchè non funzionava.

servertelnet.h
Codice:
#ifndef SERVERTELNET_H
#define SERVERTELNET_H

#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>

const int8_t ERRSOCKET=-1;
const int8_t ERRBIND=-2;
const int8_t ERRCLIENTSOCKET=-3;
const uint16_t BUFFERSIZE=512;

using namespace std;

class ServerTelnet
{
public:
    ServerTelnet();
    int8_t createSocket(uint16_t port);
    void closeSocket(void);
    string receiveData(void);
    int8_t sendData(string pkg);
    int16_t getPort(void);
    int64_t getSocketDescriptor(void);
    int64_t getClientSocket(void);
    int8_t acceptConnection(void);
    int8_t checkConn(void);

private:
    int64_t socketDescriptor;
    int64_t clientSocket;
    uint16_t tcpPort;
    struct sockaddr_in server , client;
};

#endif // SERVERTELNET_H
main.cpp
Codice:
#include <iostream>
#include <algorithm>
#include "servertelnet.h"
#include <signal.h>
using namespace std;

const uint8_t CIAO=0;
const uint8_t BUONGIORNO=1;
const uint8_t QUIT=2;
const uint8_t HELP=3;
const uint8_t STRINGEMPTY=100;


int main(void)
{
    uint8_t i;
    vector<string> cmd={"CIAO","BUONGIORNO","QUIT","HELP"};

    ServerTelnet s;

    cout << "Server in attesa..." << endl;

    if(s.createSocket(8888) < 0)
    {
        perror("Errore");
        exit(0);
    }

    string str;

    while(1)
    {
        s.checkConn();
        str=s.receiveData();

        transform(str.begin(), str.end(), str.begin(), ::toupper);

        if(s.getClientSocket() == -1) s.acceptConnection();

        for(i=0; i < cmd.size(); i++) if(cmd[i]==str) break;
        if(str=="") i=STRINGEMPTY;

        switch(i)
        {
            case CIAO:
                s.sendData("Ciao anche da me\n");
                break;

            case BUONGIORNO:
                s.sendData("Buonanotte\n");
                break;

            case QUIT:
                s.sendData("Fine sessione!\n");
                s.closeSocket();
                break;

            case HELP:
                for(i=0; i < cmd.size(); i++)
                {
                    s.sendData(cmd[i]);
                    s.sendData("\n");
                }
            break;

            case STRINGEMPTY:
                break;

            default:
                s.sendData("Comando sconosciuto!\n");
        }
    }
}
Allora, con questo codice, risponde correttamente ai vari comandi, se digito quit mi chiude la sessione e poi rilanciando un nuovo accept() posso ricollegarmi tranquillamente, però se chiudo brutalmente telnet mi si chiude brutalmente anche il server con un bel SIGPIPE (che ho visto solo ora).
Quindi, visto che la segnalazione del sigpipe l'ho vista solo ora potrei provare ad intercettarla, non ho la più pallida idea di come si faccia ma confermatemi se può essere la strada giusta.
Visto che ci siete, se conoscete il C++ mi dite anche se ci sono errori nell'implementazione della classe?
Grazie.

Stefano
stefanoxjx è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 17:28   #6
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
Io di solito uso il C su Linux comunque visto che nel codice C++ che hai scritto vedo solo C praticamente... quando la connessione è chiusa dal client la read() dovrebbe ritornarti con 0 (attento non leggi il byte '0x00', ma il valore di ritorno è proprio 0 che nel modo perverso di Linux significa End of File ovvero "Caduta Connessione") a quel punto tu chiudi la connessione dal tuo lato e ritorni in attesa di una nuova connessione.

Altro consiglio usa la funzione select() così potrai ascoltare eventuali input da tastiera (per esempio per chiudere il server con CONTROL+C), gestire i dati in input dal / dai client e una nuova connessione da un client (aggiungendo ai socket gestiti da select() il socket di listen appunto) tutto "contemporaneamente".

In molti casi comunque per rilevare velocemente lo scollegamento almeno su Linux dove SO_KEEPALIVE non sembra fare proprio nulla è avere un comando di ping da inviare di continuo a tutti i client per vedere se sono ancora vivi... è triste, ma alla fine è il modo più sicuro
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!
fano è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 18:29   #7
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da stefanoxjx Guarda i messaggi
Su listen() ho specificato 3 connessioni anche se in realtà una volta messo a punto tutto volevo portare il valore a 1.
In realta' la listen serve solo per marcare la socket come passiva, ed il numero seguente e' il numero di connessioni client pendenti.
Infatti se la esegui con il debugger, ti accorgerai che l'esecuzione non si ferma li', ma la listen() viene eseguita subito e si prosegue fino alla accept().
L'esecuzione verra' fermata alla accept() fintanto che si rende disponibile un client e la socket con il client viene creata.

In effetti, cosi' come hai scritto il codice, il tuo server effettuera' solo una accept(); una volta accettata la connessione con il client, vai ad operare con il client connesso e non accetterai piu' ulteriori client, almeno fino a quando il client attuale non chiudera' la connessione. Il tuo server pertanto puo' interagire con un solo client alla volta. Un po' poco, vero?
Comunque non disperare, questa cosa la puoi vedere sicuramente dopo.

Volevo farti notare una cosa:
Codice:
string ServerTelnet::receiveData(void)
{
    char clientMessage[BUFFERSIZE];
    int16_t readSize;

    //cout << clientSocket << endl;
    //perror("boh");
    //cout << errno << endl;

    checkConn();

    if(clientSocket==-1) return("");

    //Legge i dati
    readSize=recv(clientSocket,clientMessage, BUFFERSIZE , 0);

    //Termina il buffer togliend gli ultimi due caratteri \r\n
    if(readSize > 2) clientMessage[readSize-2]=0;
    else clientMessage[0]=0;

    //Ritorna il   dato letto convertito in string
    return(string(clientMessage));
}
Stai leggendo i dati da uno stream (tcp/ip = stream). Tcp/ip ti garantisce
- che i dati spediti arrivino;
- che arrivino nell'ordine giusto;
Tuttavia, non ti garantisce che arrivino tutti insieme! Potresti spedire "Hello, world" e potrebbe arrivare "Hello," immediatamente, ma " world" potrebbe arrivare con il pacchetto successivo.
In questo caso la tua receiveData() avrebbe dei problemi: ritornerebbe un pezzo del valore che ti aspetti (quindi non lo riconosceresti nei comandi che hai implementato); poi arriverebbe l'altro pezzo e non riconosceresti nemmeno quello!

Infine, come dicevo: se fai una read() BLOCCANTE (i.e. resti sulla socket fintanto che ricevi qualcosa), riconoscerai immediatamente la situazione di chiusura della socket da parte del client, anche nel caso che il client vada in crash e non abbia modo di chiudere la socket.
Normalmente restare bloccati su una read non e' un buon stile di programmazione in un server, ma puo' essere utile in questa fase del progetto, per avere immediatamente la notifica di errore a disposizione.
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 18:47   #8
stefanoxjx
Senior Member
 
L'Avatar di stefanoxjx
 
Iscritto dal: Jul 2002
Città: Padova
Messaggi: 4245
Quote:
Originariamente inviato da fano Guarda i messaggi
Io di solito uso il C su Linux comunque visto che nel codice C++ che hai scritto vedo solo C praticamente...
Effettivamente nel codice che ho scritto di C++ c'è solo la struttura.
Sto cercando di cambiare mentalità e passare dal procedurale agli oggetti ma dopo anni di programmazione procedurale non è per niente facile
Devo dire però che nella struttura del C++ ho già trovato alcuni vantaggi.
Per esempio riesco a gestire meglio il codice, nel senso che lo trovo più ordinato.
Altra cosa che mi piace è il fatto di avere delle variabili che possiamo definire globali nella classe senza obbligatoriamente doverle passare come parametro ad ogni metodo/funzione.

Quote:
quando la connessione è chiusa dal client la read() dovrebbe ritornarti con 0 (attento non leggi il byte '0x00', ma il valore di ritorno è proprio 0 che nel modo perverso di Linux significa End of File ovvero "Caduta Connessione") a quel punto tu chiudi la connessione dal tuo lato e ritorni in attesa di una nuova connessione.
Ora mi metti in crisi (o forse no).
Avevo già provato questa soluzione ma a mio avviso non funzionava.
Forse avevo interpretato male lo zero di ritorno.
Mi ci ributto e faccio ulteriori prove.

Quote:
Altro consiglio usa la funzione select() così potrai ascoltare eventuali input da tastiera (per esempio per chiudere il server con CONTROL+C), gestire i dati in input dal / dai client e una nuova connessione da un client (aggiungendo ai socket gestiti da select() il socket di listen appunto) tutto "contemporaneamente".
La funzione select() non la conosco proprio, vedrò di approfondire.

Quote:
In molti casi comunque per rilevare velocemente lo scollegamento almeno su Linux dove SO_KEEPALIVE non sembra fare proprio nulla è avere un comando di ping da inviare di continuo a tutti i client per vedere se sono ancora vivi... è triste, ma alla fine è il modo più sicuro
Questa è una soluzione che avevo pensato anch'io, ma non saprei come generare un pacchetto di ping (beata ignoranza ).
Hai per caso qualche link o due righe di codice da passarmi?

Grazie.
stefanoxjx è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 19:06   #9
stefanoxjx
Senior Member
 
L'Avatar di stefanoxjx
 
Iscritto dal: Jul 2002
Città: Padova
Messaggi: 4245
Quote:
Originariamente inviato da sottovento Guarda i messaggi
In realta' la listen serve solo per marcare la socket come passiva, ed il numero seguente e' il numero di connessioni client pendenti.
Infatti se la esegui con il debugger, ti accorgerai che l'esecuzione non si ferma li', ma la listen() viene eseguita subito e si prosegue fino alla accept().
L'esecuzione verra' fermata alla accept() fintanto che si rende disponibile un client e la socket con il client viene creata.
Si si, con debug avevo già visto questa cosa.

Quote:
In effetti, cosi' come hai scritto il codice, il tuo server effettuera' solo una accept(); una volta accettata la connessione con il client, vai ad operare con il client connesso e non accetterai piu' ulteriori client, almeno fino a quando il client attuale non chiudera' la connessione. Il tuo server pertanto puo' interagire con un solo client alla volta. Un po' poco, vero?
Comunque non disperare, questa cosa la puoi vedere sicuramente dopo.
Si lo so, ma per iniziare ho usato questo approccio per incasinarmi meno.
Al momento mi basta la comunicazione con un solo client.

Quote:
Volevo farti notare una cosa:
Codice:
string ServerTelnet::receiveData(void)
{
    char clientMessage[BUFFERSIZE];
    int16_t readSize;

    //cout << clientSocket << endl;
    //perror("boh");
    //cout << errno << endl;

    checkConn();

    if(clientSocket==-1) return("");

    //Legge i dati
    readSize=recv(clientSocket,clientMessage, BUFFERSIZE , 0);

    //Termina il buffer togliend gli ultimi due caratteri \r\n
    if(readSize > 2) clientMessage[readSize-2]=0;
    else clientMessage[0]=0;

    //Ritorna il   dato letto convertito in string
    return(string(clientMessage));
}
Stai leggendo i dati da uno stream (tcp/ip = stream). Tcp/ip ti garantisce
- che i dati spediti arrivino;
- che arrivino nell'ordine giusto;
Tuttavia, non ti garantisce che arrivino tutti insieme! Potresti spedire "Hello, world" e potrebbe arrivare "Hello," immediatamente, ma " world" potrebbe arrivare con il pacchetto successivo.
In questo caso la tua receiveData() avrebbe dei problemi: ritornerebbe un pezzo del valore che ti aspetti (quindi non lo riconosceresti nei comandi che hai implementato); poi arriverebbe l'altro pezzo e non riconosceresti nemmeno quello!
Ah, questo non lo sapevo.
Ma quindi, peggiorando ulteriormente la cosa se invio "Hello world", potrebbe arrivare anche "He", poi "llo" e "world"!?!?
Quindi mi conviene sempre controllare che sul pacchetto arrivato ci sia un "\r\n" finale per capire se è completo?

Quote:
Infine, come dicevo: se fai una read() BLOCCANTE (i.e. resti sulla socket fintanto che ricevi qualcosa), riconoscerai immediatamente la situazione di chiusura della socket da parte del client, anche nel caso che il client vada in crash e non abbia modo di chiudere la socket.
Normalmente restare bloccati su una read non e' un buon stile di programmazione in un server, ma puo' essere utile in questa fase del progetto, per avere immediatamente la notifica di errore a disposizione.
Capito, ma io sto effettivamente facendo un read bloccante.
Nel frattempo che rispondevo a te ho fatto la prova sul parametro di ritorno della funzione recv() come spiegato da FANO e chiarita la cosa come me l'ha spiegata lui sembra che funzioni

Sicuramente salterà fuori qualche altro problema, vi prego di non mandarmi a quel paese se vi romperò un po' le scatole
Grazie.

Stefano
stefanoxjx è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 19:44   #10
71106
Bannato
 
Iscritto dal: Nov 2014
Messaggi: 292
Quote:
Originariamente inviato da sottovento Guarda i messaggi
In realta' il server dovrebbe accorgersi immediatamente anche se la socket e' chiusa in maniera irregolare (per esempio se il client e' killato) se e' in attesa su una read.
Ripeto: se il client e' killato il sistema operativo si occupa comunque di inviare i pacchetti TCP necessari a chiudere la connessione, ma nella casistica "mia sorella e' inciampata sul cavo" non esiste modo di avere una notifica immediata. L'unica sono i pacchetti di keepalive.
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 20:43   #11
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da 71106 Guarda i messaggi
Ripeto: se il client e' killato il sistema operativo si occupa comunque di inviare i pacchetti TCP necessari a chiudere la connessione, ma nella casistica "mia sorella e' inciampata sul cavo" non esiste modo di avere una notifica immediata. L'unica sono i pacchetti di keepalive.
Beh si, stavamo dicendo la stessa cosa...
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 20:47   #12
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da stefanoxjx Guarda i messaggi

Ah, questo non lo sapevo.
Ma quindi, peggiorando ulteriormente la cosa se invio "Hello world", potrebbe arrivare anche "He", poi "llo" e "world"!?!?
Esatto!

Quote:
Originariamente inviato da stefanoxjx Guarda i messaggi
Quindi mi conviene sempre controllare che sul pacchetto arrivato ci sia un "\r\n" finale per capire se è completo?
Si. Oppure all'inizio potresti implementare un protocollo piu' semplice (per esempio, messaggi tutti della stessa lunghezza, ecc.). Comunque hai ragione, dovresti controllare se hai ricevuto tutto il comando fino ad arrivare al new line.
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 20:51   #13
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da 71106 Guarda i messaggi
Ripeto: se il client e' killato il sistema operativo si occupa comunque di inviare i pacchetti TCP necessari a chiudere la connessione, ma nella casistica "mia sorella e' inciampata sul cavo" non esiste modo di avere una notifica immediata. L'unica sono i pacchetti di keepalive.
Senti un po': so che hai sempre delle buone idee.... hai controllato il mio thread? Magari hai un buon suggerimento per me
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 09-12-2016, 23:59   #14
71106
Bannato
 
Iscritto dal: Nov 2014
Messaggi: 292
Quote:
Originariamente inviato da sottovento Guarda i messaggi
Senti un po': so che hai sempre delle buone idee.... hai controllato il mio thread? Magari hai un buon suggerimento per me
Wat...?

A 'sto punto siamo, mi vengono a cercare negli altri thread.

Se parli di questo, non ho la piu' pallida idea di che roba sia. La parentesi "Microsoft" della mita e' stata completamente chiusa qualche anno fa.
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 10-12-2016, 00:02   #15
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da 71106 Guarda i messaggi
Wat...?

A 'sto punto siamo, mi vengono a cercare negli altri thread.

Se parli di questo, non ho la piu' pallida idea di che roba sia. La parentesi "Microsoft" della mita e' stata completamente chiusa qualche anno fa.
Fortunato te! Pazienza, ci ho provato.
Chiedo scusa a tutti per l'off topic
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 10-12-2016, 15:02   #16
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
Quote:
Originariamente inviato da sottovento Guarda i messaggi
Esatto!

Si. Oppure all'inizio potresti implementare un protocollo piu' semplice (per esempio, messaggi tutti della stessa lunghezza, ecc.). Comunque hai ragione, dovresti controllare se hai ricevuto tutto il comando fino ad arrivare al new line.
Se vuoi una cosa più seria potresti fare in modo che i tuoi messaggi siano fatti così con un header anche molto semplice:

Codice:
typedef struct {
     msg_type_t msg_type;
     size_t msg_len;
} header_t;
msg_type_t sarà un enum che per esempio ha i valori "GREETING, PING, ..." se il messaggio prevede un body sarà diverso da 0.

Quindi la tua routine di lettura:

1. Legge sempre quanti byte sono un header_t
2. Analizzi il valore di ritorno di read se è 0, la connessione è caduta, se è -1 hai avuto un errore ---> sei fritto!
3. Se vuoi essere paranoico controlla anche che rc sia uguale alla sizeof di header_t così da proteggerti dalla short read
4. OK l'header è corretto analizza msg_type e decidi cosa fare in base a quello
5. Se il msg_type prevede un body procedi a leggerlo è lungo header.msg_len

Il messaggio di ping è appunto banale è un semplice header con valore PING dipende da te cosa il client risponde potrebbe essere anche l'echo del messaggio inviato... lo invii ad intervalli regolari ed attendi la risposta (per dire ogni 3 secondi lo invii, ne aspetti 2 per la risposta e se non la ottieni: connessione caduta!)

A quel punto - però - telnet non andrà più bene come client ovviamente visto che di quell'header binario da me proposto se ne frega altamente
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!

Ultima modifica di fano : 10-12-2016 alle 15:05.
fano è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker DJI RS 5: stabilizzazione e tracking intelligent...
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequen...
Le soluzioni FSP per il 2026: potenza e IA al centro Le soluzioni FSP per il 2026: potenza e IA al ce...
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa AWS annuncia European Sovereign Cloud, il cloud ...
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto Redmi Note 15 Pro+ 5G: autonomia monstre e displ...
Xiaomi 17: ecco il prezzo europeo del to...
Google fa tremare l'industria dei videog...
Gli sviluppatori 'abbandonano' Xbox: il ...
Galaxy S27 Ultra, è già te...
PlayStation Portal con display OLED: Son...
POCO X8 Pro e Pro Max sono quasi pronti:...
OpenAI ha bisogno di nuovi fondi: NVIDIA...
Mese nuovo, rinnovo delle offerte Amazon...
Accessori auto imperdibili su Amazon: pu...
Gli utenti iPhone possono ridurre la pr...
Come fare affari con l'usato garantito d...
Il miglior tablet di tutta Amazon, DOOGE...
Gli smartphone in super offerta su Amazo...
Produttori di memoria più severi ...
WhatsApp Business, Meta introduce costi ...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 22:37.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v