Il protocollo TCP (Transmission Control Protocol) fa parte della "Internet Protocolo Suite" (anche definita TCP/IP suite) ed è uno dei più usati nel mondo delle comunicazioni digitali. Tramite il meccanismo degli acknowledgements, consente una trasmissione affidabile e ordinata dei dati. Altra caratteristica importante da sottolineare è il fatto che il TCP è un protocollo orientato alla connessione: prima di trasmettere effettivamente i dati è necessario stabilire una connessione tra client e server e mantenerla attiva finché la comunicazione non finisce. Mediante il protocollo TCP è possibile garantire inoltre una comunicazione full duplex e con un flusso di byte di lunghezza variabile.
Il protocollo UDP (User Datagram Protocol) è di tipo connectionless (non richiede che si stabilisca una connessione prima dell’invio dei dati) e non affidabile (non garantisce la ricezione corretta e completa dei dati e non viene eseguito nessun controllo su una possibile perdita di datagram). I pacchetti vengono quindi inviati al destinatario senza assicurarsi che esso li abbia ricevuti. Per questi motivi questo protocollo garantisce comunicazioni a bassa latenza (oltre a quanto già detto, i messaggi sono anche più corti perché non si utilizzano byte per le informazioni di controllo) e non esiste controllo di flusso (ordinamento dei datagrammi e controllo degli errori).
I socket sono un’astrazione software per rappresentare un’interfaccia di comunicazione e si possono vedere come degli intermediari tra il livello di trasposto e il livello applicazione dello stack TCP/IP. Socket locali e remoti in comunicazione formano una coppia composta da indirizzo e porta di client e server, si instaura quindi una connessione logica tra loro.
Nel progetto sviluppato si è scelto quindi di utilizzare una comunicazione basata su socket UDP per il trasferimento dei frames dal client al server (nello specifico
da uno smartphone Android ad un computer) perché era necessaria una comunicazione veloce, che non si interrompesse nel caso in cui venissero persi pacchetti o se si perdesse
la connessione. Per il trasferimento delle stringhe contenenti le posizioni delle camere invece si è preferito utilizzare socket TCP, principalmente per essere sicuri che
i dati venissero ricevuti corretti ed in ordine.
Per fare ciò è stata utilizzata la libreria PraticalSocket.
Si espone ora brevemente lo schema logico del programma:
void HandleTCPClient(TCPSocket *sock) { cout << "Handling client "; try { cout << sock->getForeignAddress() << ":"; } catch (SocketException e) { cerr << "Unable to get foreign address" << endl; } try { cout << sock->getForeignPort(); } catch (SocketException e) { cerr << "Unable to get foreign port" << endl; } cout << endl; }
bool ReadFrames(cv::Mat &frame) { unsigned short servPort = LOCAL_PORT; UDPSocket sock(servPort); char buffer[BUF_LEN]; // Buffer of received frame int recvMsgSize; // Size of received message string sourceAddress; // Address of datagram source unsigned short sourcePort; // Port of datagram source try{ do { recvMsgSize = sock.recvFrom(buffer, BUF_LEN, sourceAddress, sourcePort); } while ((unsigned)recvMsgSize > sizeof(int)); int total_pack = ((int* ) buffer)[0]; char* longbuf = new char[PACK_SIZE * total_pack]; for (int i = 0; i < total_pack; i++) { recvMsgSize = sock.recvFrom(buffer, BUF_LEN, sourceAddress, sourcePort); if (recvMsgSize != PACK_SIZE) { continue; } memcpy( & longbuf[i * PACK_SIZE], buffer, PACK_SIZE); } cv::Mat rawData = cv::Mat(1, PACK_SIZE * total_pack, CV_8UC1, longbuf); frame = cv::imdecode(rawData, CV_LOAD_IMAGE_COLOR); if(frame.empty()){ cerr << endl << "Failed to load image" << endl; } if (frame.size().width == 0) { cerr << "decode failure!" << endl; return false; } free(longbuf); return true; } catch (SocketException & e) { cerr << e.what() << endl; return false; } }
void *SendFile(void* arg) { struct thread_args *my_arg = (struct thread_args*) arg; char BufferString[BUF_STRING_LEN]; char *res; while(1) { res=fgets(BufferString, BUF_STRING_LEN, (*my_arg).fin); if( res==NULL) break; (*my_arg).TCPServer->send(BufferString, strlen(BufferString)); } fclose((*my_arg).fin); wait_TCP = 0; pthread_exit(0); }