elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  ¿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 5,216 veces)
Dealer098

Desconectado Desconectado

Mensajes: 4


Wow!


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

¡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: 625



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

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
Wiki

Desconectado Desconectado

Mensajes: 3.158


I'Love...!¡.


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

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
  1.  
  2. /***
  3. CallBack RequestData
  4. -> Esta clase es friend de CSockBase, CSockClient y CSockServer.
  5. ***/
  6.  
  7. void*
  8. myCallDataArrival
  9. (
  10. void* p // Puntero a la clase Base CSockBase
  11. )
  12. {
  13.    char* szBuff = NULL;
  14.    char* szNewBuff = NULL;
  15.    int iRetSize = 0;
  16.    LPCSOCKBASE t = (LPCSOCKBASE)p;
  17.  
  18.    if (!t)
  19.    {
  20.        t->threadDataArrival = {};
  21.        pthread_exit(NULL);
  22.        return NULL;
  23.    }
  24.  
  25.    szBuff = new char[t->uiBuffRcv];
  26.  
  27.    do
  28.    {
  29.        iRetSize = recv(t->mySock, szBuff, t->uiBuffRcv, 0);
  30.  
  31.        if (iRetSize == SOCKET_ERROR || iRetSize == 0 ) // ¿Se ha desconectado el Socket?...
  32.            break;  //  Exit do|while(1)
  33.  
  34.        szNewBuff = new char[t->udtBuffRcv.size + iRetSize];
  35.  
  36.        memcpy(szNewBuff, t->udtBuffRcv.szData, t->udtBuffRcv.size);
  37.        memcpy(&szNewBuff[t->udtBuffRcv.size], szBuff, iRetSize);
  38.  
  39.        delete t->udtBuffRcv.szData;
  40.  
  41.        t->udtBuffRcv.szData = szNewBuff;
  42.        t->udtBuffRcv.size += iRetSize;
  43.  
  44.        if (t->pEventDataArrival != NULL)
  45.        { //Activacion del evento de Recepcion de Datos...
  46.            pthread_mutex_lock(&t->mutexDataArrival); // Bloquemos para que no se creen mas de los necesarios.
  47.            t->pEventDataArrival(t); // evento Volatile
  48.            pthread_mutex_unlock(&t->mutexDataArrival); // Habilitamos.
  49.        }
  50.    }
  51.    while(1);
  52.  
  53.    t->close();// Cerramos...
  54.  
  55.    if (t->pEventClosed)
  56.        t->pEventClosed(t);
  57.  
  58.    t->threadDataArrival = {};
  59.    pthread_exit(NULL);
  60.  
  61.    return NULL;
  62. }
  63.  
  64.  


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

The Dark Shadow is my passion.
Dealer098

Desconectado Desconectado

Mensajes: 4


Wow!


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

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
  1. #include <sys/socket.h>
  2. #include <arpa/inet.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <time.h>
  7.  
  8. int sockfd, newsock;
  9.  
  10. int main (int argc, char *argv [])
  11. {
  12. printf ("Code 0.1 - Dealer 2011\n");
  13. if (argc != 2) { printf ("Use: %s <port>\n\n", argv [0]); return 1; }
  14.  
  15. int cont = 0;
  16. struct sockaddr_in client, host;
  17. char buffer [1024];
  18. int size=sizeof (client);
  19.  
  20. sockfd=socket (2, 1 ,  0);
  21. host.sin_family=AF_INET;
  22. host.sin_port=htons (atoi (argv [1]));
  23. host.sin_addr.s_addr=0;
  24. bind (sockfd, (struct sockaddr*)&host, sizeof (struct sockaddr));
  25. listen (sockfd, 1);
  26.  
  27. while (1)
  28. {
  29. newsock=accept (sockfd, (struct sockaddr*)&client, &size);
  30. printf ("Got connection from %s:%d\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port));
  31.  
  32. while (cont != -1)
  33. {
  34. time_t now=time (0);
  35. struct tm *ahora;
  36. ahora=localtime ((const time_t*)&now);
  37. strftime (buffer, 1024, "%d/%m/%Y %H:%M:%S \n" , ahora);
  38. buffer [strlen (buffer)] = 0;
  39. cont=send (newsock, &buffer, strlen (buffer), 0);
  40. sleep (1);
  41. }
  42.  
  43. printf ("Finishing connection from %s:%d\n\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port));
  44. close (newsock);
  45. }
  46. close (sockfd);
  47. return 0;
  48. }
  49.  
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
Wiki

Desconectado Desconectado

Mensajes: 3.158


I'Love...!¡.


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

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

The Dark Shadow is my passion.
Sagrini

Desconectado Desconectado

Mensajes: 107


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

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

Arkangel_0x7C5


Desconectado Desconectado

Mensajes: 361



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

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

Código
  1. ulong ReadSZ = 0;
  2. wsock->Ioctlsocket(hSocket,FIONREAD,&ReadSZ);
  3. if(ReadSZ){
  4. //Se recibieron datos
  5. //Codigo de recv
  6. return ReadSZ;
  7. }else{
  8. //No hay datos
  9. ReadSZ = wsock->Recv(hSocket,0,0,MSG_PEEK);
  10. if(!(ReadSZ+1)){
  11. //A habido un error
  12. switch(wsock->WsaGetLastError()){
  13. case WSAEWOULDBLOCK:
  14. break;
  15. case WSAECONNRESET:
  16. //Se cerro la conexion
  17. default:
  18. //errror
  19. return -1;
  20. }
  21. }else{
  22. //Se cerro la conexion
  23. return -1;
  24. }
  25. }
  26.  

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: 107


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

Yo lo dejaría así:

Código
  1. #include <sys/socket.h>
  2. #include <arpa/inet.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <time.h>
  7.  
  8. int sockfd, newsock;
  9.  
  10. int main (int argc, char *argv [])
  11. {
  12. printf ("Code 0.1 - Dealer 2011\n");
  13. if (argc != 2) { printf ("Use: %s <port>\n\n", argv [0]); return 1; }
  14.  
  15. int cont = 0;
  16. struct sockaddr_in client, host;
  17. char buffer [1024];
  18. int size=sizeof (client);
  19.  
  20. sockfd=socket (2, 1 ,  0);
  21. host.sin_family=AF_INET;
  22. host.sin_port=htons (atoi (argv [1]));
  23. host.sin_addr.s_addr=0;
  24. bind (sockfd, (struct sockaddr*)&host, sizeof (struct sockaddr));
  25. listen (sockfd, 1);
  26.  
  27. while (1)
  28. {
  29. newsock=accept (sockfd, (struct sockaddr*)&client, &size);
  30. printf ("Got connection from %s:%d\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port));
  31.  
  32. do
  33. {
  34. time_t now=time (0);
  35. struct tm *ahora;
  36. ahora=localtime ((const time_t*)&now);
  37. strftime (buffer, 1024, "%d/%m/%Y %H:%M:%S \n" , ahora);
  38. buffer [strlen (buffer)] = 0;
  39. cont=send (newsock, &buffer, strlen (buffer), 0);
  40. sleep (1);
  41. } while (cont == strlen (buffer));
  42.  
  43. printf ("Finishing connection from %s:%d\n\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port));
  44. close (newsock);
  45. }
  46. close (sockfd);
  47. return 0;
  48. }
  49.  
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
cerrado de puertos « 1 2 »
Programación Visual Basic
Codename!! 16 4,562 Último mensaje 17 Octubre 2005, 16:34 pm
por Codename!!
CERRADO
Java
Norbs 6 4,873 Último mensaje 26 Noviembre 2008, 13:50 pm
por Norbs
Cerrado!
.NET (C#, VB.NET, ASP)
mr_marley 0 1,946 Último mensaje 3 Agosto 2010, 18:33 pm
por mr_marley
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines