elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.
 
Inicio Ayuda Buscar Ingresar Registrarse
28 Mayo 2012, 22:28  


Tema destacado: Suscripción al boletín mensual de elhacker.net

+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse)
| | |-+  ¿Socket cerrado?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: ¿Socket cerrado?  (Leído 781 veces)
Dealer098

Desconectado Desconectado

Mensajes: 4


Wow!


Ver Perfil
¿Socket cerrado?
« en: 20 Diciembre 2011, 23:20 »

¡Buenas de nuevo! Estaba haciendo probaturas con sockets en C, Linux, y se me ha ocurrido una pregunta.
¿Cómo puedo detectar que el cliente/host ha perdido la conexión? Pongo un ejemplo: Tengo un programa que se conecta a cierta IP con cierto puerto. Ahora, al conectarse, recibe datos del servidor. Si corto la conexión de este programa, ¿cómo puedo hacer que el servidor "reaccione"? Hay que tener en cuenta que el programa no envía datos, sólo recibe. ¿Qué se os ocurre?

Un saludo. Dealer.


En línea

Stupid silly boy... xD
naderST


Desconectado Desconectado

Mensajes: 467



Ver Perfil
Re: ¿Socket cerrado?
« Respuesta #1 en: 21 Diciembre 2011, 05:59 »

La manera mas fácil de hacerlo es enviar un mensaje al cliente cada cierto tiempo y si la función send() retorna SOCKET_ERROR quiere decir que se perdió la conexión. Otra manera es con la función select() investiga un poco sobre ello.


En línea
BlackZeroX (Astaroth)
Wiki

Desconectado Desconectado

Mensajes: 2.831


I'Love...!¡.


Ver Perfil WWW
Re: ¿Socket cerrado?
« Respuesta #2 en: 22 Diciembre 2011, 12:49 »

cuando creas el socket crea un hilo que manipute recv() con el buffer predeterminado del SO, si retorna SOCKET_ERROR o 0 (Son dos casos particulares), es que el Socket se ha cerrado abruptamente, este metodo es el que uso y SIEMPRE me ha servidor!¡.

por ejemplo yo uso este proceso para detectar dicho evento:

Código
 
/***
CallBack RequestData
-> Esta clase es friend de CSockBase, CSockClient y CSockServer.
***/

 
void*
myCallDataArrival
(
void* p // Puntero a la clase Base CSockBase
)
{
   char* szBuff = NULL;
   char* szNewBuff = NULL;
   int iRetSize = 0;
   LPCSOCKBASE t = (LPCSOCKBASE)p;
 
   if (!t)
   {
       t->threadDataArrival = {};
       pthread_exit(NULL);
       return NULL;
   }
 
   szBuff = new char[t->uiBuffRcv];
 
   do
   {
       iRetSize = recv(t->mySock, szBuff, t->uiBuffRcv, 0);
 
       if (iRetSize == SOCKET_ERROR || iRetSize == 0 ) // ¿Se ha desconectado el Socket?...
           break;  //  Exit do|while(1)
 
       szNewBuff = new char[t->udtBuffRcv.size + iRetSize];
 
       memcpy(szNewBuff, t->udtBuffRcv.szData, t->udtBuffRcv.size);
       memcpy(&szNewBuff[t->udtBuffRcv.size], szBuff, iRetSize);
 
       delete t->udtBuffRcv.szData;
 
       t->udtBuffRcv.szData = szNewBuff;
       t->udtBuffRcv.size += iRetSize;
 
       if (t->pEventDataArrival != NULL)
       { //Activacion del evento de Recepcion de Datos...
           pthread_mutex_lock(&t->mutexDataArrival); // Bloquemos para que no se creen mas de los necesarios.
           t->pEventDataArrival(t); // evento Volatile
           pthread_mutex_unlock(&t->mutexDataArrival); // Habilitamos.
       }
   }
   while(1);
 
   t->close();// Cerramos...
 
   if (t->pEventClosed)
       t->pEventClosed(t);
 
   t->threadDataArrival = {};
   pthread_exit(NULL);
 
   return NULL;
}
 
 


Dulces Lunas!¡.
« Última modificación: 22 Diciembre 2011, 12:57 por BlackZeroX (Astaroth) » En línea

Web Principal-->[ Blog(VB6) | Host File (Public & Private) | Scan Port | (New)MyInfraPC (Descubre mi Contraseña venefi. $) ]



The Dark Shadow is my passion.
El infierno es mi Hogar, mi novia es Lilith y el metal mi
Dealer098

Desconectado Desconectado

Mensajes: 4


Wow!


Ver Perfil
Re: ¿Socket cerrado?
« Respuesta #3 en: 22 Diciembre 2011, 14:03 »

La primera idea ya la he puesto en práctica, pero nada. La segunda es demasiado enrevesada para lo que quiero hacer, pero gracias.

Os dejo el código que tengo y un resumen del problema:
Código
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
 
int sockfd, newsock;
 
int main (int argc, char *argv [])
{
printf ("Code 0.1 - Dealer 2011\n");
if (argc != 2) { printf ("Use: %s <port>\n\n", argv [0]); return 1; }
 
int cont = 0;
struct sockaddr_in client, host;
char buffer [1024];
int size=sizeof (client);
 
sockfd=socket (2, 1 ,  0);
host.sin_family=AF_INET;
host.sin_port=htons (atoi (argv [1]));
host.sin_addr.s_addr=0;
bind (sockfd, (struct sockaddr*)&host, sizeof (struct sockaddr));
listen (sockfd, 1);
 
while (1)
{
newsock=accept (sockfd, (struct sockaddr*)&client, &size);
printf ("Got connection from %s:%d\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port));
 
while (cont != -1)
{
time_t now=time (0);
struct tm *ahora;
ahora=localtime ((const time_t*)&now);
strftime (buffer, 1024, "%d/%m/%Y %H:%M:%S \n" , ahora);
buffer [strlen (buffer)] = 0;
cont=send (newsock, &buffer, strlen (buffer), 0);
sleep (1);
}
 
printf ("Finishing connection from %s:%d\n\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port));
close (newsock);
}
close (sockfd);
return 0;
}
 
Código:
$ gcc -o serv serv.c
$ ./serv 31337
Code 0.1 - Dealer 2011
Got connection from 127.0.0.1:48677
$
$ gdb -q serv
Leyendo símbolos desde /home/juanra/Escritorio/serv...(no se encontraron símbolos de depuración)hecho.
(gdb) r 31337
Starting program: /home/juanra/Escritorio/serv 31337
Code 0.1 - Dealer 2011
Got connection from 127.0.0.1:48678

Program received signal SIGPIPE, Broken pipe.
0x0012d422 in __kernel_vsyscall ()
(gdb)
Código:
$ nc -vv 127.0.0.1 31337
Connection to 127.0.0.1 31337 port [tcp/*] succeeded!
22/12/2011 13:57:09
22/12/2011 13:57:10
22/12/2011 13:57:11
22/12/2011 13:57:12
22/12/2011 13:57:13
^C
$ nc -vv 127.0.0.1 31337
Connection to 127.0.0.1 31337 port [tcp/*] succeeded!
22/12/2011 13:57:33
22/12/2011 13:57:34
22/12/2011 13:57:35
22/12/2011 13:57:36
^C
$
A ver: El primer code es el código del servidor. El segundo es la terminal desde la que se ejecuta code. El tercero muestra los procesos de netcat, que se conecta al servidor corriendo en la segunda terminal, y que tras pocos segundos recibe una interrupción ^C para interrumpir la conexión. En el momento de la interrupción, la idea es que la segunda terminal (la del servidor) mostrase un mensaje diciendo que la conexión se ha finalizado. Ahora, el problema es que al cortar desde netcat la conexión, hay un error que nos muestra el GDB al correr el servidor desde el depurador. Dice que el error es por "broken pipe". Tras varias pruebas, he visto que el "error" se producía cuando se cortaba la conexión y la ejecución del programa llega a la revisión del while. ¿Por qué? ¿Alguna idea?
PS: Evidentemente, los dos programas (servidor y nc) corren a la vez. Un saludo. Dealer
En línea

Stupid silly boy... xD
BlackZeroX (Astaroth)
Wiki

Desconectado Desconectado

Mensajes: 2.831


I'Love...!¡.


Ver Perfil WWW
Re: ¿Socket cerrado?
« Respuesta #4 en: 22 Diciembre 2011, 21:37 »

Si tu idea es detectar de manera automatica dicho evento vas a tener que usar HILOS + Semaforos o Mutex quieras o no (Es lo mas viable), la de mandar a cada rato algo con send no es viable...

Un ejemplo mas completo (OJO solo el Cliente)... NO esta terminado ese ejemplo pero la idea de como detectar la desconexion de un Socket esta en  void myCallDataArrival(CSocketBase* t)... esta en C++...

Dulces Lunas!¡.
En línea

Web Principal-->[ Blog(VB6) | Host File (Public & Private) | Scan Port | (New)MyInfraPC (Descubre mi Contraseña venefi. $) ]



The Dark Shadow is my passion.
El infierno es mi Hogar, mi novia es Lilith y el metal mi
Sagrini

Desconectado Desconectado

Mensajes: 104

Visit las Vegas ;)


Ver Perfil WWW
Re: ¿Socket cerrado?
« Respuesta #5 en: 23 Diciembre 2011, 16:52 »

Mmm... creo que el problema está en la línea de "while (cont != -1)", que no debería ser -1. Prueba a ver con otros valores que no sean -1 :P Ni idea!
En línea

Un saludo. Sagrini
Arkangel_0x7C5

Conectado Conectado

Mensajes: 298



Ver Perfil
Re: ¿Socket cerrado?
« Respuesta #6 en: 23 Diciembre 2011, 21:10 »

yo detecto la desconexion usando socket asíncronos, lo detecto al usar recv

Código
ulong ReadSZ = 0;
wsock->Ioctlsocket(hSocket,FIONREAD,&ReadSZ);
if(ReadSZ){
//Se recibieron datos
//Codigo de recv
return ReadSZ;
}else{
//No hay datos
ReadSZ = wsock->Recv(hSocket,0,0,MSG_PEEK);
if(!(ReadSZ+1)){
//A habido un error
switch(wsock->WsaGetLastError()){
case WSAEWOULDBLOCK:
break;
case WSAECONNRESET:
//Se cerro la conexion
default:
//errror
return -1;
}
}else{
//Se cerro la conexion
return -1;
}
}
 

La cosa es que si ReadSZ es zero no hay datos para leer, y al usar rcv si la conexio se cierra bien da 0 y si se cierra mal da SOCKET_ERROR y LastError = WSAECONNRESET.
En línea

Sagrini

Desconectado Desconectado

Mensajes: 104

Visit las Vegas ;)


Ver Perfil WWW
Re: ¿Socket cerrado?
« Respuesta #7 en: 29 Diciembre 2011, 19:37 »

Yo lo dejaría así:

Código
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
 
int sockfd, newsock;
 
int main (int argc, char *argv [])
{
printf ("Code 0.1 - Dealer 2011\n");
if (argc != 2) { printf ("Use: %s <port>\n\n", argv [0]); return 1; }
 
int cont = 0;
struct sockaddr_in client, host;
char buffer [1024];
int size=sizeof (client);
 
sockfd=socket (2, 1 ,  0);
host.sin_family=AF_INET;
host.sin_port=htons (atoi (argv [1]));
host.sin_addr.s_addr=0;
bind (sockfd, (struct sockaddr*)&host, sizeof (struct sockaddr));
listen (sockfd, 1);
 
while (1)
{
newsock=accept (sockfd, (struct sockaddr*)&client, &size);
printf ("Got connection from %s:%d\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port));
 
do
{
time_t now=time (0);
struct tm *ahora;
ahora=localtime ((const time_t*)&now);
strftime (buffer, 1024, "%d/%m/%Y %H:%M:%S \n" , ahora);
buffer [strlen (buffer)] = 0;
cont=send (newsock, &buffer, strlen (buffer), 0);
sleep (1);
} while (cont == strlen (buffer));
 
printf ("Finishing connection from %s:%d\n\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port));
close (newsock);
}
close (sockfd);
return 0;
}
 
En línea

Un saludo. Sagrini
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
(cerrado)
Chats; IRC y Messengers
NaNih 2 422 Último mensaje 30 Septiembre 2006, 23:49
por NaNih
(cerrado)
Programación C/C++
NaNih 4 578 Último mensaje 3 Octubre 2006, 12:22
por NaNih
¡¡El gobierno reconoce que hay crisis!! cerrado el cerrado? xD « 1 2 »
Foro Libre
BenRu 20 2,060 Último mensaje 22 Julio 2008, 17:09
por -HadeS-
CERRADO
Java
Norbs 6 1,451 Último mensaje 26 Noviembre 2008, 13:50
por Norbs
Cerrado!
.NET
mr_marley 0 614 Último mensaje 3 Agosto 2010, 18:33
por mr_marley
Powered by SMF 1.1.16 | SMF © 2006-2008, Simple Machines