public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Question about sockets
       [not found] <9ab7eeeb0807262031m1b25ec88r5a425a5c09f96c8d@mail.gmail.com>
@ 2008-07-27 20:51 ` Leonardo Santagostini
  2008-07-28  3:23   ` Eljay Love-Jensen
  0 siblings, 1 reply; 3+ messages in thread
From: Leonardo Santagostini @ 2008-07-27 20:51 UTC (permalink / raw)
  To: gcc-help

[-- Attachment #1: Type: text/plain, Size: 294 bytes --]

Hi list !!!!
I have a problem closing sockets.

All the code is well done except when the program terminates the thread.

Attached is the code.

Look, the program is very simple but is not working fine at all,
because the sockets remains in TIME_WAIT or CLOSE_WAIT state.

Any clue ???

Thanks

[-- Attachment #2: sockets.c --]
[-- Type: application/octet-stream, Size: 26394 bytes --]

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <libxml/xmlreader.h>
#include <mysql.h>
                                                                                                             
#define SUCCESS 0
#define ERROR   1
#define SERVER_PORT 12345
#define ADM_PORT 5678
#define MAX_MSG 5000
#define MAXCONN 500

typedef struct 
{
	int nroComercio;
	unsigned int connMax;
	unsigned int connActual;
	int rechazos;
	int recokcti; 
	int revercti;
	int recokmov;
	int revermov;
	int recokper;
	int reverper;
	int cantconreq;
} tabConnXcomm;

int readnf (int, char *);
int readline(int, char *, int);
int envio(int, char *);

struct trxData{
    char trxUsuario[50];
    char trxClave[50];
    char trxTipoTrans[50];
    char trxIdenTrans[50];
    char trxIdenComer[50];
    char trxFacturador[50];
    char trxCodServicio[50];
    char trxRefPago[50];
    char trxMonto[50];
};
                                                                                                   
int server, decido, trxok, trxnook;
xmlDoc *doc = NULL;
xmlNode *root_element = NULL;
struct trxData trx;
tabConnXcomm tablaComercios[10];

static void cargoValores(xmlNode * a_node)
{
    xmlNode *cur_node = NULL;
	xmlChar *valor;
	int i = 0;

    for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
        if (cur_node->type == XML_ELEMENT_NODE) {
			
			valor = xmlNodeGetContent(cur_node);
			
			if(strcmp((char*)cur_node->name,"numero")==0)
			{
				tablaComercios[i].nroComercio = atoi(valor);
			}

			if (strcmp((char*)cur_node->name,"maximo")==0)
			{
				i--;
				tablaComercios[i].connMax = atoi(valor);
			}	
			tablaComercios[i].connActual = 0;
			i++;
        }
        cargoValores(cur_node->children);
    }
}

static void procesoRecargadores( void )
{
    xmlDoc *doc = NULL;
    xmlNode *root_element = NULL;

	doc = xmlReadFile("./recargadores.xml", NULL, 0);

    if (doc == NULL) {
        printf("error: could not parse file\n");
    }

    root_element = xmlDocGetRootElement(doc);

    cargoValores(root_element);
	xmlFreeDoc(doc);

    xmlCleanupParser();
}

static void procesarXml(xmlNode * a_node, struct trxData * trx)
{
	xmlNode *cur_node = NULL;
	xmlChar *valor;

	for (cur_node = a_node; cur_node; cur_node = cur_node->next) 
	{
		if (cur_node->type == XML_ELEMENT_NODE) 
		{
			valor = xmlNodeGetContent(cur_node);
			if(strcmp((char*)cur_node->name,"usuario")==0)
			{
				strcpy(trx->trxUsuario, (char*)valor);
			}
			if(strcmp((char*)cur_node->name,"clave")==0)
			{
				strcpy(trx->trxClave, (char*)valor);
			}
			if(strcmp((char*)cur_node->name,"tipo_trans")==0)
			{
				strcpy(trx->trxTipoTrans, (char*)valor);
			}
			if(strcmp((char*)cur_node->name,"iden_trans")==0)
			{
				strcpy(trx->trxIdenTrans, (char*)valor);
			}
			if(strcmp((char*)cur_node->name,"iden_comercio")==0)
			{
				strcpy(trx->trxIdenComer, (char*)valor);
			}
			if(strcmp((char*)cur_node->name,"facturador")==0)
			{
				strcpy(trx->trxFacturador, (char*)valor);
			}
			if(strcmp((char*)cur_node->name,"cod_servicio")==0)
			{
				strcpy(trx->trxCodServicio, (char*)valor);
			}
			if(strcmp((char*)cur_node->name,"referencia_pago")==0)
			{
				strcpy(trx->trxRefPago, (char*)valor);
			}
			if(strcmp((char*)cur_node->name,"monto")==0)
			{
				strcpy(trx->trxMonto, (char*)valor);
			}
			xmlFree(valor);
		}
		procesarXml(cur_node->children, trx);
	}
}

void cleanup() //Funcion que se ocupa de matar toda la suciedad
{
	printf("Limpiese y archivese !!!\n");
	close(server);
	pthread_exit(NULL);
	return;
} /* cleanup() */

void handler(void * paramsd) //Funcion llamada cuando nace un thread
{
	struct sockaddr_in cliAddr;
	char line[MAX_MSG];
	pthread_t threadid;
	int client_local, i, numBytes, resResp;
	unsigned int addr_len;
	client_local = *((int *)paramsd);
	addr_len = sizeof(cliAddr);
	threadid = pthread_self();
	getpeername(client_local, (struct sockaddr*)&cliAddr, &addr_len);
	memset(line, 0x00, MAX_MSG);
	xmlDoc *doc = NULL;
    xmlNode *root_element = NULL;
    struct trxData trx;	
	char respuesta[250];
	
	strcpy(respuesta,"<?xml version=\"1.0\"?><RecargaVirtual_respuesta><tipo_trans>R</tipo_trans><iden_trans_rgp></iden_trans_rgp><estado>1</estado><descripcion>ERROR CARRIER NO DISPONIBLE</descripcion></RecargaVirtual_respuesta>\n\0");
	resResp=strlen(respuesta)+1;
	respuesta[resResp-1]='\0';

	
    trx.trxUsuario[0]=0;
    trx.trxClave[0]=0;
    trx.trxTipoTrans[0]=0;
    trx.trxIdenTrans[0]=0;
    trx.trxIdenComer[0]=0;
    trx.trxFacturador[0]=0;
    trx.trxCodServicio[0]=0;
    trx.trxRefPago[0]=0;
    trx.trxMonto[0]=0;

	while(readnf(client_local, line)!=ERROR)
	{
		if (!strcmp(line,""))
			break;

		// Proceso el XML recibido
		
		doc = xmlReadMemory(line, strlen(line), "noname.xml", NULL, 0);
	    if (doc == NULL) {
	                printf("\t* No se puedo parsear el XML recibido\n");
	        break;
	    }
	    root_element = xmlDocGetRootElement(doc);
	    procesarXml(root_element, &trx);
	    xmlFreeDoc(doc);
	    
			if(strcmp(trx.trxTipoTrans,"R") == 0) // busco si es recarga o anulacion
			{
				fprintf(stdout, "\t* Es una recarga....\n");
				for(i=0; i < 10; i++)
				{
					if( tablaComercios[i].nroComercio == atoi(trx.trxIdenComer))
					{
						fprintf(stdout, "\t* Coincide numero de comercio: %d\n", tablaComercios[i].nroComercio);
						fprintf(stdout, "\t* Aplico Canilla\n");
						fprintf(stdout, "\t* Agregando a contadores un nuevo requerimiento de conexion...\n");
						tablaComercios[i].cantconreq++;
						fprintf(stdout, "\t* Comercio numero: %d, Conexiones Maximas permitidas: %d, Conexiones usandose: %d\n", tablaComercios[i].nroComercio, tablaComercios[i].connMax, tablaComercios[i].connActual);
						if (tablaComercios[i].connActual < tablaComercios[i].connMax)
						{
							tablaComercios[i].connActual++;
							fprintf(stdout, "\t* Conexiones maximas: %d\tConexiones actuales: %d\n", tablaComercios[i].connMax, tablaComercios[i].connActual);
							// chequeo de que facturador es la recarga.
							if(atoi(trx.trxFacturador) == 1) // recarga movistar
								tablaComercios[i].recokmov++;
							if(atoi(trx.trxFacturador) == 3)
								tablaComercios[i].recokcti++;
							if(atoi(trx.trxFacturador) == 4)
								tablaComercios[i].recokper++;
							// llamo a la funcion envio (int descriptor, char * cadena) para trabajar con el socket
							if ( envio(client_local, line) == SUCCESS)
							{
								fprintf(stdout, "\t* Operacion realizada con exito!\n");
								tablaComercios[i].connActual--;
								break;
							}
							else
							{
								fprintf(stdout, "\t* Termine el proceso y decremente.\n\t ** Conexiones maximas: %d\tConexiones actuales: %d\n", tablaComercios[i].connMax, tablaComercios[i].connActual);
								tablaComercios[i].connActual--;
								break;
							}
						}
						else
						{
							fprintf(stdout, "\t* Se supero el maximo de conexiones [%d] para el comercio: %d\n", tablaComercios[i].connMax, tablaComercios[i].nroComercio);
							tablaComercios[i].rechazos++;
							if ( (numBytes = send(client_local, respuesta, resResp, 0)) == -1)
							{
								perror("\t* Error enviando datos\n");
							}
							else 
							{
								fprintf(stdout, "\t* Se ha enviado mensaje de error de %d bytes al recargador \n", numBytes);		
								fprintf(stdout, "\t* Incrementando la cantidad de rechazos...\n");
								break;
							}
						}
					}
					else
					{
						if ( i == 9 )
						{
							fprintf(stdout, "\t* Numero de comercio %d no encontrado...NO se aplica canilla...\n", atoi(trx.trxIdenComer));
							if ( envio(client_local, line) == SUCCESS)
							{
								fprintf(stdout, "\t* Operacion realizada con exito!\n");
								break;
							}
							else
							{
								fprintf(stdout, "\t* Termine el proceso\n");
								break;
							}
						}
					}

				} //for de busqueda de comercio
			}
			else // es anulacion
			{
				if(strcmp(trx.trxTipoTrans,"A") == 0) // es anulacion
				{
					for(i=0; i < 10; i++) // recorro la lista para los contadores
					{
						if( tablaComercios[i].nroComercio == atoi(trx.trxIdenComer)) // me fijo si encuentro el comercio
						{
							// debo hacer el matcheo para los contadores
							tablaComercios[i].cantconreq++;

							if(atoi(trx.trxFacturador) == 1)
								tablaComercios[i].revermov++;
							if(atoi(trx.trxFacturador) == 3)
								tablaComercios[i].revercti++;
							if(atoi(trx.trxFacturador) == 4)
								tablaComercios[i].reverper++;
							if ( envio(client_local, line) == SUCCESS)
							{
								fprintf(stdout, "\t* Operacion realizada con exito!\n");
								break;
							}
							else
							{
								fprintf(stdout, "\t* Termine el proceso\n");
								break;
							}
						}
					}
					break;
				} 
				else
					fprintf(stdout, "\t* Llego cualquier cosa distinto de una Recarga... NO se aplica canilla...\n");
					if ( envio(client_local, line) == SUCCESS)
					{
						fprintf(stdout, "\t* Operacion realizada con exito!\n");
						break;
					}
					else
					{
						fprintf(stdout, "\t* Termine el proceso\n");
						break;
					}
			}
			fprintf(stdout, "\t***** Peticion finalizada *****\n"); 
			memset(line,0x00,MAX_MSG);		
	}

	fflush(stdout);
	memset(cliAddr.sin_zero, 0, 8); 
	close(client_local);
	pthread_detach(threadid);
	pthread_exit(NULL);
	cleanup();
} /* handler() */

void fcAdminMenu (void * parametros)
{
	struct sockaddr_in cliAddr;
	pthread_t threadid;
	int socket_cliente, lonBufferMenu, resMenu, i, j, numComercio;
	unsigned int addr_len;
	socket_cliente = *((int *)parametros);
	addr_len = sizeof(cliAddr);
	threadid = pthread_self();
	getpeername(socket_cliente, (struct sockaddr*)&cliAddr, &addr_len);
	char bufferMenu[MAX_MSG], bufferEntradaMenu[MAX_MSG], bufferSalida[MAX_MSG], bufferTmp[MAX_MSG];
	memset(bufferMenu, 0, 0); 
	memset(bufferEntradaMenu, 0, 0); 
	memset(bufferSalida, 0, 0); 
	i=0;

	strcpy(bufferMenu,"\nBienvenido, seleccione una opcion:\nA.Alta recargador\nB.Baja Recargador\nL.Listado Recargadores\nM.Modificacion\nEleccion:");
	lonBufferMenu = strlen(bufferMenu);
	bufferMenu[lonBufferMenu] = '\0';

	fprintf(stdout, "\t\t* Admin. Envio pantalla de opciones...\n");
	if ( (resMenu = send(socket_cliente, bufferMenu, lonBufferMenu+1, 0)) == -1)
	{
		perror("\t\t* Admin. Error enviando datos\n");
	}
	else
	{
		fprintf(stdout, "\t\t* Admin. Se han enviado %d bytes.\n", resMenu);
	}

	if ((resMenu = recv(socket_cliente, bufferEntradaMenu, MAX_MSG,0)) == -1) 
	{
		perror("\t\t* Admin. Error recibiendo datos\n");
	}

	// Una vez enviados los datos, me quedo esperando por la respuesta
	fprintf(stdout, "\t\t* Admin. Se han recibido %d bytes de respuesta...\n", resMenu);
	bufferEntradaMenu[resMenu] = '\0';
	fprintf(stdout, "\t\t* Admin. Se recibio: %s\n", bufferEntradaMenu);

	/* Analizo la respuesta:
		A: Alta de un nuevo recargador
		B: Baja de un recargador
		L: Listado
		M: Modificacion
	*/

	fprintf(stdout,"\t\t* Admin. Longitud del buffer: %d\n", strlen(bufferEntradaMenu));
	bufferEntradaMenu[1] = '\0';
	fprintf(stdout,"\t\t* Admin. Longitud 2 del buffer: %d\n", strlen(bufferEntradaMenu));

	if (!strcmp(bufferEntradaMenu,""))
		exit(1);

	if (!strcmp(bufferEntradaMenu,"A"))
	{
		fprintf(stdout, "\t\t* Admin. Se recibio un alta de recargador\n");
		memset(bufferMenu, 0, 0); 
		memset(bufferEntradaMenu, 0, 0); 
		memset(bufferSalida, 0, 0); 
		for(i=0; i < 10; i++)
		{
			if( (tablaComercios[i].nroComercio) == 0 )
			{
				sprintf(bufferSalida, "Ingrese el numero de comercio seguido de ENTER...\n");
				j = strlen(bufferSalida);
				if ( (resMenu = send(socket_cliente, bufferSalida, j, 0)) == -1)
				{
					perror("\t\t* Admin. Error enviando datos\n");
				}
				if ((resMenu = recv(socket_cliente, bufferEntradaMenu, MAX_MSG,0)) == -1) 
				{
					perror("\t\t* Admin. Error recibiendo datos\n");
				}
				
				fprintf(stdout, "\t\t* Admin. Se recibio: %s Guardando los datos en estructura\n", bufferEntradaMenu);
				bufferEntradaMenu[resMenu-1] = '\0';
				tablaComercios[i].nroComercio = atoi(bufferEntradaMenu);
				
				memset(bufferMenu, 0, 0); 
				memset(bufferEntradaMenu, 0, 0); 
				memset(bufferSalida, 0, 0); 
				j=0;

				sprintf(bufferSalida, "Ingrese el numero maximo de conexiones para el comercio seguido de ENTER...\n");
				j = strlen(bufferSalida);

				if ( (resMenu = send(socket_cliente, bufferSalida, j, 0)) == -1)
				{
					perror("\t\t* Admin. Error enviando datos\n");
				}
				if ((resMenu = recv(socket_cliente, bufferEntradaMenu, MAX_MSG,0)) == -1) 
				{
					perror("\t\t* Admin. Error recibiendo datos\n");
				}
			
				fprintf(stdout, "\t\t* Admin. Se recibio: %s Guardando los datos en estructura\n", bufferEntradaMenu);
				bufferEntradaMenu[resMenu] = '\0';
				tablaComercios[i].connMax = atoi(bufferEntradaMenu);
				break;
			}
			else
			{
				fprintf(stdout,"\t\t* Admin. No se han encontrado posiciones vacias para dar de alta un comercio...\n");
			}
		}

	}

	if (!strcmp(bufferEntradaMenu,"B" ))
	{
		fprintf(stdout, "\t\t* Admin. Se recibio un req. de baja de recargador\n");
		sprintf(bufferSalida, "Ingrese el numero de comercio seguido de ENTER...\n");
		j = strlen(bufferSalida);
		resMenu=0;

		if ( (resMenu = send(socket_cliente, bufferSalida, j, 0)) == -1)
		{
			perror("\t\t* Admin. Error enviando datos\n");
		}
		if ((resMenu = recv(socket_cliente, bufferEntradaMenu, MAX_MSG,0)) == -1) 
		{
			perror("\t\t* Admin. Error recibiendo datos\n");
		}
		bufferEntradaMenu[resMenu-1] = '\0';
		numComercio = atoi(bufferEntradaMenu);
		fprintf(stdout, "\t\t* Admin. Se recibio %d numero de comercio \n", numComercio);

		for(i=0; i < 10; i++)
		{
			if( (tablaComercios[i].nroComercio) == numComercio )
			{
				fprintf(stdout, "\t\t* Admin. Se han encontrado numero de comercio\n");
				fprintf(stdout, "\t\t* Admin. Borrando todos los datos para comercio: %d", numComercio);
				tablaComercios[i].nroComercio = 0;
				tablaComercios[i].connMax = 0;
				break;
			}
			else
				fprintf(stdout, "\t\t* Admin. No se ha encontrado el Numero de comercio en la lista\n");
		}
	}

	if (!strcmp(bufferEntradaMenu,"L" ))
	{
		fprintf(stdout, "\t\t* Admin. Se recibio un req. de listado de recargadores\n");
		resMenu=0;

		bufferSalida[0] = '\0';		
		strcpy(bufferSalida, "Comercio | MaxConn | ConnActivas | Rechazadas | Rec./Rev.CTI | Rec./Rev.Movistar | Rec./Rev.Personal | Con.Requeridas |\n");
		strcat(bufferSalida, "----------------------------------------------------------------------------------------------------------------------|\n");
		for (i=0; i<10; i++)
		{
			bufferTmp[0]='\0';

			sprintf(bufferTmp, "  %05d  |   %02d    |     %02d      |       %04d | %04d/%04d    | %04d/%04d         | %04d/%04d         | %04d           |\n", 
									tablaComercios[i].nroComercio, tablaComercios[i].connMax, tablaComercios[i].connActual,
									tablaComercios[i].rechazos, tablaComercios[i].recokcti, 
									tablaComercios[i].revercti, tablaComercios[i].recokmov, 
									tablaComercios[i].revermov,tablaComercios[i].recokper, 
									tablaComercios[i].reverper, tablaComercios[i].cantconreq);
			
			strcat(bufferSalida, bufferTmp);

		}
					
		j=strlen(bufferSalida);
		bufferSalida[j]='\0';

		if ( (resMenu = send(socket_cliente, bufferSalida, j, 0)) == -1)
		{
			perror("\t\t* Admin. Error enviando datos\n");
		}

			fflush(stdout);
	}

	if (!strcmp(bufferEntradaMenu,"M" ))
	{
		fprintf(stdout, "\t\t* Admin. Se recibio req. de modificacion de recargadores\n");
		sprintf(bufferSalida, "Ingrese el numero de comercio seguido de ENTER...\n");
		j = strlen(bufferSalida);
		resMenu=0;

		if ( (resMenu = send(socket_cliente, bufferSalida, j, 0)) == -1)
		{
			perror("\t\t* Admin. Error enviando datos\n");
		}
		if ((resMenu = recv(socket_cliente, bufferEntradaMenu, MAX_MSG,0)) == -1) 
		{
			perror("\t\t* Admin. Error recibiendo datos\n");
		}
		bufferEntradaMenu[resMenu-1] = '\0';
		numComercio = atoi(bufferEntradaMenu);
		fprintf(stdout, "\t\t* Admin. Se recibio %d numero de comercio \n", numComercio);

		for(i=0; i < 10; i++)
		{
			if( (tablaComercios[i].nroComercio) == numComercio )
			{
				fprintf(stdout, "\t\t* Admin. Se han encontrado numero de comercio: %d\n", tablaComercios[i].nroComercio);

				sprintf(bufferSalida, "Ingrese el numero maximo de conexiones para el comercio seguido de ENTER...\n");
				j = strlen(bufferSalida);

				if ( (resMenu = send(socket_cliente, bufferSalida, j, 0)) == -1)
				{
					perror("\t\t* Admin. Error enviando datos\n");
				}
				if ((resMenu = recv(socket_cliente, bufferEntradaMenu, MAX_MSG,0)) == -1) 
				{
					perror("\t\t* Admin. Error recibiendo datos\n");
				}
				
				fprintf(stdout, "\t\t* Admin. Se recibio: %s Guardando los datos en estructura\n", bufferEntradaMenu);
				bufferEntradaMenu[resMenu] = '\0';
				tablaComercios[i].connMax = atoi(bufferEntradaMenu);

				break;
			}
		}
	}

	fflush(stdout);
	i=0;
	j=0;
	memset(cliAddr.sin_zero, 0, 8); 
	close(socket_cliente);
	pthread_detach(threadid);
	pthread_exit(NULL);
	cleanup();
} /* fcAdminMenu */


void fcAdmin (void)
{
	int adm, cliente;
	unsigned int addr_len;
	pthread_t threadAdmin;
	threadAdmin = pthread_self();
	struct sockaddr_in admAddr;
	struct sockaddr_in cliAddr;

	adm = socket(PF_INET, SOCK_STREAM, 0);
	if (adm < 0) 
	{
		perror("\t\t* Admin. No puedo abrir socket administrativo: ");
		return;
	}
	
	//Preparo el socket ADM
	admAddr.sin_family = AF_INET;
	admAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	admAddr.sin_port = htons(ADM_PORT);

	//Cero la estructura
	memset(admAddr.sin_zero, 0, 8);
	memset(cliAddr.sin_zero, 0, 8);

	//Hago el bind
	if (bind(adm, (struct sockaddr *) &admAddr, sizeof(struct sockaddr)) < 0 )
	{
		perror("\t\t* Admin. No puedo bindearme al puerto administrativo");
		return;
	}

	//Me quedo escuchando...
	listen(adm, MAXCONN);

	while(1)
	{

		fprintf(stdout, "\t\t* Admin. Esperando datos en puerto: %u\n", ADM_PORT);
		addr_len = sizeof(cliAddr);

		cliente = accept(adm, (struct sockaddr *) &cliAddr, &addr_len);
		if (cliente < 0) 
		{
			perror("\t\t* Admin. No puedo aceptar conexion ");
		}

		fprintf(stdout, "\t\t* Admin. Llego una peticion ***\n");
		pthread_create(&threadAdmin, 0, (void*)&fcAdminMenu, (void*) &cliente);
	}		

	memset(cliAddr.sin_zero, 0, 8);
	close(adm);
	fflush(stdout);
	pthread_detach(threadAdmin);
	pthread_exit(NULL);
	cleanup();
} /* fcAdmin() */

void fcFlusher(void)
{
	// Declaro las variables que voy a usar para el mysql
	MYSQL *conn;
	char myhost[20] ;
	char myuser[15] ;
	char mypass[15] ;
	char mydb[20] ;
	strcpy(myhost, "127.0.0.1");
	strcpy(myuser, "root");
	strcpy(mypass, "");
	strcpy(mydb, "estadisticas");
	time_t curtime;
	struct tm *loctime;
	char query[400];
	char buffer[240];
	int i;
	pthread_t threadFlusher;

	// Una vez inicializadas las variables debo:
	/*
		1) Entrar en un loop
		2) Esperar 5 minutos
		3) Recorrer la estructura de los recargadores e ir insertando esos datos en DDBB
		4) Despues de insertar en DDBB, cerar los contadores para cada comercio
	*/

	while(1)
	{
		curtime = time (NULL);
		loctime = localtime (&curtime);
		query[0]='\0';
		buffer[0]='\0';
		
		fprintf(stdout, "\t\t\t* Fecha hora: %04d-%02d-%02d %02d:%02d:%02d\n", loctime->tm_year+1900, loctime->tm_mon+1, loctime->tm_mday, loctime->tm_hour, loctime->tm_min, loctime->tm_sec);
		fprintf(stdout, "\t\t\t* Esperando 5 minutos para insertar en base y cerar estruturas...\n");
		sleep(300); // valor puesto en 30 seg para pruebas, cambiar

		// Ha pasado el tiempo de espera, ejecutando trabajo...
		fprintf(stdout, "\t\t\t* Flusheando datos de estructuras de memoria a DB...\n");

		conn = mysql_init(NULL);
		
		if (!mysql_real_connect(conn, myhost, myuser, mypass, mydb, 0, NULL, 0))
		{
		   fprintf(stderr, "\t\t\t* %s\n", mysql_error(conn));
		   exit(1);
		}		

		// recorro el vector con estructuras de recargadores...
		for (i=0; i<10; i++)
		{
			if (tablaComercios[i].nroComercio != 0)
			{
				sprintf(buffer, "insert into conexionesRV (nrocomercio, connmax, connact, rechazos, recokcti, "
								"revercti, recokmov, revermov, recokper, reverper, conreq, fechahora) "
								"values (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, now());",
								tablaComercios[i].nroComercio,
								tablaComercios[i].connMax,
								tablaComercios[i].connActual,
								tablaComercios[i].rechazos,
								tablaComercios[i].recokcti,
								tablaComercios[i].revercti,
								tablaComercios[i].recokmov,
								tablaComercios[i].revermov,
								tablaComercios[i].recokper,
								tablaComercios[i].reverper,
								tablaComercios[i].cantconreq);

				// en este punto estoy listo para hacer el insert
				if (mysql_query(conn, buffer))
				{
					fprintf(stderr, "\t\t\t* %s\n", mysql_error(conn));
					exit(1);
				}
				buffer[0]='\0';

				// inicializo los contadores
				tablaComercios[i].rechazos=0;
				tablaComercios[i].recokcti=0; 
				tablaComercios[i].revercti=0; 
				tablaComercios[i].recokmov=0;
				tablaComercios[i].revermov=0; 
				tablaComercios[i].recokper=0; 
				tablaComercios[i].reverper=0; 
				tablaComercios[i].cantconreq=0;

			}

		} /* fin for recorro el vector con estructuras de recargadores */
		mysql_close(conn);

	} /* while */

	fflush(stdout);
	pthread_detach(threadFlusher);
	pthread_exit(NULL);
	cleanup();
} /* fcFlusher */

int main (int argc, char *argv[])
{
	int client, rc, tr;
	unsigned int addr_len;
	pthread_t thread;
	struct sockaddr_in cliAddr;
	struct sockaddr_in servAddr;

	fprintf(stdout, "* Inicializando programa...\n");
	
	trxok = 0;
	trxnook = 0;
	decido = 0;
	
	signal(SIGINT, cleanup);
	signal(SIGTERM, cleanup);

	fprintf(stdout, "* Procesando XML con recargadores...\n");
	procesoRecargadores();

	//Asigno a server el FD de un socket
	server = socket(PF_INET, SOCK_STREAM, 0);
	if (server < 0) 
	{
		perror(" ** No puedo abrir socket: ");
		return ERROR;
	}

	// Voy preparando la estructura socaddr_in
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servAddr.sin_port = htons(SERVER_PORT);

	//Cero las tres estructuras
	memset(servAddr.sin_zero, 0, 8);
	memset(cliAddr.sin_zero, 0, 8);

	//Hago el Bind
	if (bind(server, (struct sockaddr *) &servAddr, sizeof(struct sockaddr)) < 0) 
	{
		perror("** No puedo bindearme al puerto ");
		return ERROR;
	}

	// Creo el socket Administrativo en un thread Separado
	fprintf(stdout, "* Creando socket administrativo...\n");
	rc = pthread_create(&thread, 0, (void*) &fcAdmin, NULL);

	fprintf(stdout, "* Llamando a funcion flusher...\n");
	tr = pthread_create(&thread, 0, (void*) &fcFlusher, NULL);

	//Me pongo a escuchar en el socket
	listen(server, MAXCONN);

	fprintf(stdout, "* Esperando datos en puerto: %u\n", SERVER_PORT);
	while(1)
	{
		addr_len = sizeof(cliAddr);

		client = accept(server, (struct sockaddr *) &cliAddr, &addr_len);
		if (client < 0) 
		{
			perror("** No puedo aceptar conexion \n");
			break;
		}
		//Hago el switcheo de decido
		decido = ! decido;
		fprintf(stdout, "\n\n\t***** Llego una peticion *****\n");
		//Levanto un nuevo thread
		pthread_create(&thread, 0, (void*)&handler, (void*) &client);
		fflush(stdout);
	} /* while (1) */

	close(server);
	pthread_exit(NULL);
	exit(0);
} /* main() */

int readnf (int fd, char *line) //Chequeo si viene solo una linea
{
	if (readline(fd, line, MAX_MSG) < 0)
		return ERROR;
	return SUCCESS;
}

int readline(int fd, char *str, int maxlen) // Al final de toda la linea la cero
{
	char c;
	char * oristr;

	oristr = str;

	while ( read(fd, &c, 1) != 0 )
	{
		if (c == 0x0A || c == 0x0D || c == 0x00)
			break;
		else
		if (strlen(oristr) < maxlen-1)
		{
			*str = c;
			str++;
		}
	}

	*str=0x00;
	return (strlen(oristr));
} 

int envio(int descriptor, char *cadena) //Funcion principal
{

	struct sockaddr_in socketRV;
	int fdRV, resSend, longEnvio, resResp;
	char bufferEntrada[MAX_MSG];
	pthread_t threadid;
	
	memset(socketRV.sin_zero, 0, 8);
	memset(bufferEntrada, 0x00, MAX_MSG);
	longEnvio = strlen(cadena);
	threadid = pthread_self();
	
	socketRV.sin_family = AF_INET;
	socketRV.sin_port = htons(16789);
	socketRV.sin_addr.s_addr = inet_addr("xxx.yyy.www.zzz");
	cadena[longEnvio] = '\n';
	cadena[longEnvio+1] = '\0';

	// Abro socket al demonio RV

	fdRV = socket(PF_INET, SOCK_STREAM, 0);
	if (fdRV < 0) 
	{
		perror("\t Envio: No puedo abrir socket al RV\n");
		return ERROR;
	}
	else
		fprintf(stdout, "\t Envio: Conectado con Recarga Virtual...\n");

	if (connect(fdRV, (struct sockaddr *) &socketRV, sizeof(socketRV)) < 0) 
	{
		perror("\t Envio: Error, no puedo conectarme al Recarga Virtual ******* \n");
		return ERROR;
	}
	else	// Si todo anduvo bien, envio datos recibidos 
			// descriptor: fdRV, Datos: cadena
		fprintf(stdout, "\t Envio: Cadena a enviar: (%s)\n", cadena);
		fprintf(stdout, "\t Envio: Enviando datos al Recarga Virtual...\n");
		if ( (resSend = send(fdRV, cadena, longEnvio+1, 0)) == -1)
		{
		    perror("\t Envio: Error enviando datos\n");
		}
		else
		    fprintf(stdout, "\t Envio: Se enviaron %d bytes al Recarga Virtual...\n", resSend);

		if ((resResp = recv(fdRV, bufferEntrada, MAX_MSG,0)) == -1) 
		{
		    perror("\t Envio: Error recibiendo datos\n");
		}

			// Una vez enviados los datos, me quedo esperando por
			// la respuesta del recarga Virtual

		fprintf(stdout, "\t Envio: Se han recibido %d bytes del Recarga Virtual...\n", resResp);
		bufferEntrada[resResp] = '\0';

		if (resResp < 3)  // Significa que llego NADA
		{
			fprintf(stderr, "\t Envio: Llego nada desde el Recarga Virtual\n");
			return ERROR;
		}			

		else
			// Significa que llegaron datos desde el recarga virtual
			// Envio los datos de nuevo al recargador
			fprintf(stdout, "\t Envio: Respuesta a enviar: (%s)\n", bufferEntrada);
			fprintf(stdout, "\t Envio: Enviando respuesta del Recarga Virtual al recargador...\n");
			if ( (resSend = send(descriptor, bufferEntrada, resResp, 0)) == -1)
			{
				perror("\tError enviando datos\n");
			}
			else
				fprintf(stdout, "\t Envio: Se han enviado %d bytes al recargador.\n", resSend);		

		memset(socketRV.sin_zero, 0, 8);
		close(fdRV);
		return SUCCESS;

		fflush(stdout);
		pthread_detach(threadid);
		pthread_exit(NULL);
		cleanup();
}


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Question about sockets
  2008-07-27 20:51 ` Question about sockets Leonardo Santagostini
@ 2008-07-28  3:23   ` Eljay Love-Jensen
  2008-07-28  6:37     ` Leonardo Santagostini
  0 siblings, 1 reply; 3+ messages in thread
From: Eljay Love-Jensen @ 2008-07-28  3:23 UTC (permalink / raw)
  To: Leonardo Santagostini, GCC-help

Hi Leonardo,

The gcc-help forum is not the correct forum for socket and pthread
questions.  I do not say this to chastise you, rather to inform you that
faster, more accurate help is likely to come from a more appropriate forum.

That being said...

Your source code is too long.  Could you trim it down to a much smaller
example that exhibits the problem?

Also, when you close your socket, it does not appear that you first did a
shutdown of the socket.

man 2 close
man 2 shutdown

You may want to adjust your socket options, such as linger or timeout.

man 2 setsockopt

The CLOSE_WAIT means the remote connection has finished sending data, and
your side has not yet done a shutdown and close.

The TIME_WAIT means that both sides have close'd the connection, but the IP
stack is obliged to wait a prescribed time before taking the connection
down.  This is normal, and expected.

Also, your communication may be affected by Nagle's algorithm.  In most
cases, Nagle's algorithm is a good thing.  For certain kinds of IP
communication (what I'd call "chatty" communication), it can introduce
undesirable latency.

Sincerely,
--Eljay

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Question about sockets
  2008-07-28  3:23   ` Eljay Love-Jensen
@ 2008-07-28  6:37     ` Leonardo Santagostini
  0 siblings, 0 replies; 3+ messages in thread
From: Leonardo Santagostini @ 2008-07-28  6:37 UTC (permalink / raw)
  To: Eljay Love-Jensen, gcc-help

Thanks Eljay !

Yours,
Leonardo

2008/7/27 Eljay Love-Jensen <eljay@adobe.com>:
> Hi Leonardo,
>
> The gcc-help forum is not the correct forum for socket and pthread
> questions.  I do not say this to chastise you, rather to inform you that
> faster, more accurate help is likely to come from a more appropriate forum.
>
> That being said...
>
> Your source code is too long.  Could you trim it down to a much smaller
> example that exhibits the problem?
>
> Also, when you close your socket, it does not appear that you first did a
> shutdown of the socket.
>
> man 2 close
> man 2 shutdown
>
> You may want to adjust your socket options, such as linger or timeout.
>
> man 2 setsockopt
>
> The CLOSE_WAIT means the remote connection has finished sending data, and
> your side has not yet done a shutdown and close.
>
> The TIME_WAIT means that both sides have close'd the connection, but the IP
> stack is obliged to wait a prescribed time before taking the connection
> down.  This is normal, and expected.
>
> Also, your communication may be affected by Nagle's algorithm.  In most
> cases, Nagle's algorithm is a good thing.  For certain kinds of IP
> communication (what I'd call "chatty" communication), it can introduce
> undesirable latency.
>
> Sincerely,
> --Eljay
>
>



-- 
Saludos.-
Leonardo Santagostini

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-07-27 20:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <9ab7eeeb0807262031m1b25ec88r5a425a5c09f96c8d@mail.gmail.com>
2008-07-27 20:51 ` Question about sockets Leonardo Santagostini
2008-07-28  3:23   ` Eljay Love-Jensen
2008-07-28  6:37     ` Leonardo Santagostini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).