#include <arpa/inet.h> #include <netdb.h> #include <netinet/in.h> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui_c.h> #include <pthread.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> #include <cstdio> #include <signal.h> #define UDP_PORT 9998 #define TCP_PORT 9999 #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #define MAXLEN 1048576 //1024*1024 using namespace cv; /** CONSTANTES Y CONFIGURACION **/ const char delimiter[] = "Grupo25"; const int keepAliveIntervalSeconds = 5; const bool debug = false; // DEFINICION DE FUNCIONES int printFrame(int received_data_size, char* recibido, int fin, char* buf); void printFrameUDP(char* jpg, int size); void TCP(const char* HOST); void UDP(char* HOSTNAME); int sendDatagramUDPtoHostname(int socket, char* HOSTNAME, char* buffer, unsigned short int destinationPort); const char* getIP(char* hostname); void error(const char *); void* keepAliveMethod(void* ptr); struct keepAliveData{ int keepAliveId; int socketId; char* ip; }; volatile sig_atomic_t flag = 0; void my_function(int sig){ // can be called asynchronously flag = 1; // set flag sleep(1); } /** * Funcion auxiliar que retorna dentro del array indicando la posicion del comienzo del delimitador * array: arreglo a consultar * len: largo de array * delimiter: delimitador a buscar * inicio: desde que posicion arrancar a buscar */ int findPosDelimiter(const char *array, int len, int inicio) { int i = -1; int pos = 0; for (i = inicio; i<len; i++){ if (sizeof(delimiter)-1 == pos) if (array[i] == delimiter[pos]) return i - sizeof(delimiter) + 2; else pos=0; else if (array[i] == delimiter[pos]) pos++; else pos=0; } return -1; } void TCP(const char* HOST){ int client_socket = socket(AF_INET, SOCK_STREAM, 0); //obtenemos la direccion con getaddrinfo struct addrinfo hints, *res; memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; getaddrinfo(HOST, STR(TCP_PORT), &hints, &res); printf("Intentando conexion con %s:%d ...\n",HOST,TCP_PORT); //primitiva CONNECT if (connect(client_socket, res->ai_addr, res->ai_addrlen)<0){ printf("Error, imposible establecer conexion con el servidor.\n"); return; } //primitiva SEND char msg[4]; sprintf(msg, "%s", "TCP"); msg[3] = '\0'; int msg_size = strlen(msg); int sent_msg_size = send(client_socket, msg, msg_size, 0); if (sent_msg_size == -1) { printf("Error, imposible establecer conexion con el servidor.\n"); return; } printf("Conexion establecida.\n"); char buf[MAXLEN]; // se almacenan los datos TCP recibidos en cada recv char recibido[MAXLEN]; // mantiene el historico de datos recibidos, quitando los frames ya dibujados int fin = 0; // Mantiene el indice del array recibido. int received_data_size = 1; while(received_data_size > 0 && !flag) { int data_size = MAXLEN; received_data_size = recv(client_socket, buf, data_size, 0); fin = printFrame( received_data_size, recibido, fin, buf); } printf("Cerrando sockets a %s:%d\n", HOST, TCP_PORT); close(client_socket); freeaddrinfo(res); } int printFrame(int received_data_size, char* recibido, int fin, char* buf){ if (debug) { printf("Datos recibidos: %d\n", received_data_size); } // en el arrray 'recibido' se mantiene los datos que ya exisitian mas los nuevos. for(int j = 0; j < received_data_size; j++) recibido[fin+j] = buf[j]; fin += received_data_size; int inicio = 0; int found = -1; while ((found = findPosDelimiter(recibido, fin+1, inicio)) != -1) { char jpg[found-inicio]; for (int h = 0; h < found-inicio; h++) jpg[h] = recibido[inicio+h]; if (debug) { printf("Nuevo jpeg size: %ui\n", sizeof(jpg)); } namedWindow("cliente", CV_WINDOW_AUTOSIZE); Mat rawData = Mat(1, found, CV_8UC1, jpg); Mat frame = imdecode(rawData, CV_LOAD_IMAGE_COLOR); imshow("cliente", frame); waitKey(30); inicio = found + sizeof(delimiter)-1; } if (inicio != 0) { // mueve los datos recibidos al inicio, quitando el (o los) frame dibujado y el delimitador for (int d = inicio; d < fin+1; d++) recibido[d-inicio] = recibido[d]; fin -= inicio; } return fin; } void printFrameUDP(char* jpg, int size){ if (debug) { printf("Nuevo jpeg size: %d\n", size); } namedWindow("cliente", CV_WINDOW_AUTOSIZE); Mat rawData = Mat(1, size, CV_8UC1, jpg); Mat frame = imdecode(rawData, CV_LOAD_IMAGE_COLOR); imshow("cliente", frame); waitKey(30); } void UDP(char* HOSTNAME){ unsigned int length; struct from; // CREATE SOCKET int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) error("error when creating socket"); char buffer[256]; bzero(buffer,256); sprintf(buffer, "SUBSCRIPTION"); // ENVIO PEDIDO DE SUSCRIPCION printf("Enviando Suscripcion a %s:%d ...\n", HOSTNAME, UDP_PORT); ::fflush(stdout); if (sendDatagramUDPtoHostname(sock, HOSTNAME, buffer, UDP_PORT) < 0) error("Error on send first datagram"); // ESPERO RESPUESTA DEL SERVIDOR struct timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); bzero(buffer,256); struct sockaddr_in from; if (recvfrom(sock,buffer,256,0,(struct sockaddr *)&from, &length) < 0){ if ((errno == EAGAIN) || (errno == EWOULDBLOCK)){ printf("Error, no hay respuesta del servidor.\n"); return; }else{ printf("Error al recibir ACEEPT del servidor\n"); return; } } if (debug) { printf("Subscription: %s\n", buffer); } char* keepAliveId = new char[3]; keepAliveId[0] = buffer[9]; keepAliveId[1] = buffer[10]; keepAliveId[2] = '\0'; printf("keepAliveId is : %s\n", keepAliveId); keepAliveData* kaData = new (keepAliveData); kaData->keepAliveId = atoi(keepAliveId); kaData->socketId = sock; kaData->ip = new char[strlen(HOSTNAME)+1]; sprintf(kaData->ip, "%s" , HOSTNAME); (kaData->ip)[strlen(HOSTNAME)] = '\0'; pthread_t* hilos = new pthread_t[1]; pthread_create ( &hilos[0], NULL, keepAliveMethod, (void *)kaData ); char buf[MAXLEN]; // se almacenan los datos TCP recibidos en cada recv int received_data_size = 1; while(true && !flag) { received_data_size = recvfrom( sock , buf , MAXLEN , 0 , (struct sockaddr *)&from , &length ); if (received_data_size < 1){ if ((received_data_size < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){ printf("Error, no hay respuesta del servidor.\n"); break; }else{ printf("Error al recibir datos.\n"); break; } }else { printFrameUDP(buf, received_data_size); } } //while (true) //{ // memset ( frameBuffer , '\0' , 100 ); // if ( recvfrom( sock , frameBuffer , 100 , 0 , (struct sockaddr *)&from , &length ) < 0) // error("recv from UDP frames"); // printf("%s\n", frameBuffer); //} printf("Cerrando sockets a %s:%d, keepAliveId %s\n", HOSTNAME, UDP_PORT, keepAliveId); close(sock); } void* keepAliveMethod(void* ptr){ keepAliveData* kaData = (keepAliveData*)ptr; char* buffer = new char[13]; sprintf(buffer, "KEEPALIVE:%d", kaData->keepAliveId); buffer[13] = '\0'; while(true && !flag){ sleep(keepAliveIntervalSeconds); printf("Sending keep alive request :%d\n", kaData->keepAliveId ); sendDatagramUDPtoHostname(kaData->socketId, kaData->ip, buffer, UDP_PORT); } } int sendDatagramUDPtoHostname(int socket, char* HOSTNAME, char* buffer, unsigned short int destinationPort){ struct sockaddr_in server; server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(getIP(HOSTNAME)); server.sin_port = htons(destinationPort); return sendto( socket , buffer , strlen(buffer) , 0, (const struct sockaddr *)&server , sizeof(struct sockaddr_in) ); } void error(const char *msg) { perror(msg); exit(0); } const char* getIP(char* hostname){ struct hostent *hp = gethostbyname(hostname); if (hp==0) error("Unknown host"); char* ipAddress = NULL; struct in_addr **addr_list = (struct in_addr **)hp->h_addr_list; if(addr_list[0] != NULL){ int tam = strlen(inet_ntoa(*addr_list[0])); ipAddress = new char[tam+1]; sprintf(ipAddress, "%s", inet_ntoa(*addr_list[0])); ipAddress[tam] = '\0'; }else{ error("Unknown host"); } return ipAddress; } char* upCase(char* arg){ char* s = arg; unsigned char c; while(*s){ c = *s; *s = toupper(c); s++; } return arg; } int main(int argc, char *argv[]) { // Register signals signal(SIGINT, my_function); if (strcmp(upCase(argv[1]),"TCP") == 0){ TCP(argv[2]); }else if (strcmp(upCase(argv[1]),"UDP") == 0){ UDP(argv[2]); }else{ printf("ERROR: primer argumento debe ser TCP o UDP.\n"); return -1; } }