• Domingo 6 de Julio de 2025, 14:06

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - captaindanieo

Páginas: 1 [2]
26
C/C++ / Re: Comunicación Por Sockets
« en: Jueves 6 de Diciembre de 2007, 11:17 »
Eternal Idol, pues a mi no me realiza esas acciones al ejecutarlo.

He probado a cambiar la cadena como tu dices, pero no funciona. Ni la cadena numérica ni una cadena de letras se reciben.

En la ventana del Servidor solo se muestra lo siguiente:

Conexion Recibida
Sigo aqui en modo servidor

Esperando nuevos datos
Voy a leer
Sigo aqui en modo servidor
Sigo aqui en modo servidor
Sigo aqui en modo servidor
Sigo aqui en modo servidor
Sigo aqui en modo servidor

....


El servidor no recibe nada, y debería de hacerlo, ¿no?

Muchas gracias por las molestias. ¿Podría ser del compilador? No lo creo, ¿no? Uso el dev c++. Ya es que no se que puede estar pasando. Estoy revisando las líneas de código una por una, lo que debe de ejecutarse, y en principio debería ir. No se  :(

27
C/C++ / Re: Comunicación Por Sockets
« en: Miércoles 5 de Diciembre de 2007, 21:39 »
El socket es creado en la capa L2CAP que creamos cuando elegimos la opción cliente o servidor.

Cuando elegimos Servidor, hacemos un socketserver en el puerto 3000, y estamos ahi a la escucha, y además creamos un thread paralelo a la escucha siempre de lo que pueda venir por el socket.

Cuando elegimos Cliente se define un SocketClient por ese mismo puerto 3000, y se permanece a la escucha permanente en otro thread por si llegan datos por el puerto 3000.

Cuando el canal de la capa correspondiente a servidor realiza la llamada a Sendbytes y envía por el socket, el Cliente está a la escucha de llegada de datos por ese puerto 3000, y por tanto debería recibir la cadena enviada.

La recepción de los datos por el socket se realiza en bucleLectura, a la cual se le pasa un puntero y siempre llama a thisL2cap->leerSocket(), que es donde se realiza el ReceiveBytes().


El único socket que tengo definido es 's', en L2CAP. Ya que a los canales, les paso en el constructor un puntero a ese mismo socket s, y la variable sockCanal es simplemente una copia de dicho puntero.


Debería de funcionar, ¿no?  :(

28
C/C++ / Re: Comunicación Por Sockets
« en: Martes 4 de Diciembre de 2007, 23:18 »
Para el funcionamiento de los sockets tengo incluidas en el proyecto las bibliotecas de libwsock32.a y winsock2.h.

Son las únicas bibliotecas u objetos añadidos en las opciones de proyecto. Todo lo demás está en el código.

 :unsure:

29
C/C++ / Re: Comunicación Por Sockets
« en: Lunes 3 de Diciembre de 2007, 22:28 »
pc. es el nombre de mi computadora. En ese campo debe ir el nombre del host, de quien abre la conexión.


La línea que debería provocar la escritura es, justo en el Constructor del canal L2capchannel, la que dice:

pt2Func (_ME,"080001000205040001004000");


O sea, justo cuando creamos el canal para meterlo en el vector de canales, justo cuando lo creamos, en el costructor estamos mandando datos (esto lo hice así para probar cuanto antes el tema de los sockets).

Esa línea no es la escritura en sí, sino que provoca que se llame al Wrapper definido en L2cap (y efectivamente se le llama correctamente, ya que se muestra por pantalla un mensaje de que se está en el Wrapper).

Código: Text
  1. void L2cap::Wrapper_a_escribeEnSocket (void* pt2Object, std::string cadena)
  2. {
  3.     cout<<"Welcome to WRAPPER"<<endl;
  4.       L2cap* mySelf = (L2cap*) pt2Object;
  5.       mySelf->escribeEnSocket(cadena);
  6.      
  7.      //mySelf->sendRaw();  // Esto debería de funcionar, pero tampoco
  8. }
  9.  


En escribeEnSocket es donde se realiza la escritura en sí, y se le pasa la cadena a escribir.

En ella se realiza un SendBytes, que es lo que envía por el socket.


Muchas gracias.

30
C/C++ / Re: Comunicación Por Sockets
« en: Lunes 3 de Diciembre de 2007, 16:43 »
No logro dar con el por qué  :(

31
C/C++ / Re: Comunicación Por Sockets
« en: Domingo 2 de Diciembre de 2007, 15:28 »
Muchas gracias EternalIdol.

Sigo intentando encontrar el por qué no funciona. Estaré atento a tu respuesta cuando puedas. Muchísimas gracias.

32
C/C++ / Re: Comunicación Por Sockets
« en: Domingo 2 de Diciembre de 2007, 14:12 »
-----------------------------|  l2capChannel.cpp  |--------------------
Código: Text
  1. #include <stdlib.h>
  2. #include <iostream>
  3. #include <time.h>
  4. #include <sstream>
  5. #include <string>
  6. #include <L2capChannel.h>
  7.  
  8.  
  9. using namespace std;
  10.  
  11.  
  12.  
  13. L2capChannel::L2capChannel (int CID, int PSM, Socket* a)  // Constructor
  14. {
  15.     _estado = CLOSED;
  16.     _localCID = CID;
  17.     _PSM = PSM;
  18.     sockCanal = a;
  19.  
  20.     std::string cad = "080001000305040001004000";
  21.     sockCanal->SendBytes(cad); // No escribe, no se por que
  22. }
  23.  
  24. L2capChannel::L2capChannel (int CID, int PSM,void* a, void(*pt2Func)(void*, std::string))
  25. {
  26.     _estado = CLOSED;
  27.     _localCID = CID;
  28.     _PSM = PSM;
  29.     _ME = a;
  30.     cout<<"Se supone que enviamos!"<<endl;  
  31.     pt2Func (_ME,"080001000205040001004000"); // Llama al Wrapper y éste deberia escribir, pero no lo hace
  32.  
  33. //    _ME->sendRaw(); // deberia poder mandar asi tambien, pero no
  34. }
  35.  
  36. L2capChannel::~L2capChannel ()  // Constructor
  37. {
  38. }
  39.  
  40.  
  41.  
  42. void L2capChannel::imprimeArray (Tpdu_L2CAP datain, unsigned int longitud)
  43. {
  44.      unsigned int i;
  45.  
  46.    printf(" \n\n El array de datos es el siguiente: \n \n");      
  47.      for (i=0; i<(longitud); i++)
  48.      {
  49.          printf("%X ",*(datain+i));        
  50.      }
  51.    printf(" \n \n");
  52. }
  53.  
  54.  
  55. void L2capChannel::escribeL2CAPcon_req_TX ()
  56. {
  57.     L2CAPcon_req_TX.Code = L2CAP_CONREQ;
  58.     L2CAPcon_req_TX.ID = _identifier;              
  59.     L2CAPcon_req_TX.Length = 4;
  60.     L2CAPcon_req_TX.PSM = _PSM;
  61.     L2CAPcon_req_TX.SCID = _localCID;
  62. }
  63.  
  64.  
  65. void L2capChannel::escribeL2CAPcon_res_TX (int result)
  66. {
  67.        L2CAPcon_res_TX.Code = L2CAP_CONRES;
  68.        L2CAPcon_res_TX.ID = L2CAPcon_req_RX.ID;    
  69.        L2CAPcon_res_TX.Length = 6;
  70.        L2CAPcon_res_TX.DCID = _localCID;
  71.        L2CAPcon_res_TX.SCID = _remoteCID;
  72.        L2CAPcon_res_TX.Result = result;
  73.        L2CAPcon_res_TX.Status = 0x0000;
  74. }
  75.  
  76.  
  77.  
  78.  
  79. void L2capChannel::leerL2CAPcon_req(Tpdu_L2CAP datain, unsigned int &n)
  80. {
  81.     L2CAPcon_req_RX.Code = *(datain + n);
  82.    L2CAPcon_req_RX.ID = *(datain + n+1);    
  83.   L2CAPcon_req_RX.Length = *(datain + n+2) + (*(datain+n+3))*256;
  84.   L2CAPcon_req_RX.PSM = *(datain + n+4) + (*(datain+n+5))*256;
  85.   L2CAPcon_req_RX.SCID = *(datain + n+6) + (*(datain+n+7))*256;
  86.   int _remoteCID = L2CAPcon_req_RX.SCID;
  87.    
  88.     n += (L2CAPcon_req_RX.Length + 4);
  89.     cout<<"vamos por aqui"<<endl;
  90.  
  91.  
  92.     if (_estado==CLOSED)
  93.     {
  94.        unsigned int result=0; //successfull
  95.        if (result==0)
  96.        {
  97.           escribeL2CAPcon_res_TX (result);
  98.           _estado=WAIT_CONFIG;
  99.        }
  100.        else if (result==1) //pending
  101.        {
  102.             escribeL2CAPcon_res_TX (result);
  103.             _estado=WAIT_CONNECT;
  104.        }
  105.        else //No puede
  106.        {
  107.             escribeL2CAPcon_res_TX (result);
  108.        }
  109.        sendComando(L2CAP_CONRES);
  110.     }
  111. } // leerL2CAPcon_req
  112.  
  113.  
  114. int L2capChannel::leerL2CAPcon_res(Tpdu_L2CAP datain, unsigned int &n)
  115. {
  116.     unsigned int _receivedIdentifier = *(datain + n+1);
  117.    
  118.      switch (_estado)
  119.      {
  120.       case WAIT_CONNECT_RSP:
  121.            {
  122.                 if (L2CAPcon_req_RX.ID !=_receivedIdentifier)
  123.                 {
  124.                    cout<<"Identificador no se corresponde con el esperado."<<endl;      
  125.                    return 2;
  126.                 }
  127.            
  128.                 L2CAPcon_res_RX.Code = *(datain + n);      // Code = 03
  129.               L2CAPcon_res_RX.ID = *(datain + n+1);    
  130.               L2CAPcon_res_RX.Length = *(datain + n+2) + (*(datain+n+3))*256;
  131.               L2CAPcon_res_RX.DCID = *(datain + n+4) + (*(datain+n+5))*256;
  132.               L2CAPcon_res_RX.SCID = *(datain + n+6) + (*(datain+n+7))*256;
  133.               L2CAPcon_res_RX.Result = *(datain + n+8) + (*(datain+n+9))*256;
  134.               L2CAPcon_res_RX.Status = *(datain + n+10) + (*(datain+n+11))*256;
  135.            
  136.                 n += (L2CAPcon_res_RX.Length + 4);  
  137.                        
  138.                switch (L2CAPcon_res_RX.Result)
  139.                {
  140.                       case 0: //Success
  141.                            {
  142.                             _estado = WAIT_CONFIG;
  143.                             _remoteCID = L2CAPcon_res_RX.DCID;
  144.                             break;
  145.                            }
  146.                       case 1: //pending
  147.                            {
  148.                            break;
  149.                            }
  150.                       case 2: //Refused
  151.                            {
  152.                            _estado = CLOSED;
  153.                            cout<<"PSM not supported."<<endl;
  154.                            return -1;
  155.                            break;
  156.                            }
  157.                       case 3: //Refused
  158.                            {
  159.                            _estado = CLOSED;
  160.                            cout<<"Security block."<<endl;
  161.                            return -1;
  162.                            break;
  163.                            }
  164.                       case 4: //Refused
  165.                            {
  166.                            _estado = CLOSED;
  167.                            cout<<"No resources available."<<endl;
  168.                            return -1;
  169.                            break;
  170.                            }
  171.                            
  172.                       default:
  173.                               {
  174.                               }                      
  175.                }              
  176.                return 0;
  177.                break;
  178.            }
  179.  
  180.       default :
  181.               {
  182.                return 1;
  183.               }
  184.      }
  185. }
  186.  
  187.  
  188.  
  189. void L2capChannel::imprimeComando (unsigned int codigo)
  190. {
  191.      unsigned int i;
  192.      
  193.      switch (codigo)
  194.      {
  195.      case L2CAP_CONREQ :
  196.       {
  197.         printf("\n \n*****Connection Request******* \n");                                  
  198.         printf("El campo Code es de valor %X \n",L2CAPcon_req_RX.Code);
  199.         printf("El campo ID es de valor %X \n",L2CAPcon_req_RX.ID);
  200.         printf("El campo Length es de valor %X \n",L2CAPcon_req_RX.Length);
  201.         printf("El campo PSM es de valor %X \n",L2CAPcon_req_RX.PSM);
  202.         printf("El campo SCID es de valor %X \n \n",L2CAPcon_req_RX.SCID);
  203.       break;
  204.       }
  205.      case L2CAP_CONRES :
  206.       {
  207.         printf("\n \n*****Connection Response******* \n");                                  
  208.         printf("El campo Code es de valor %X \n",L2CAPcon_res_RX.Code);
  209.         printf("El campo ID es de valor %X \n",L2CAPcon_res_RX.ID);
  210.         printf("El campo Length es de valor %X \n",L2CAPcon_res_RX.Length);
  211.         printf("El campo DCID es de valor %X \n",L2CAPcon_res_RX.DCID);
  212.         printf("El campo SCID es de valor %X \n",L2CAPcon_res_RX.SCID);
  213.         printf("El campo Result es de valor %X \n",L2CAPcon_res_RX.Result);
  214.         printf("El campo Status es de valor %X \n \n",L2CAPcon_res_RX.Status);
  215.       break;
  216.       }
  217.      }
  218. }
  219.  
  220.  
  221. int L2capChannel::entradaComandos (Tpdu_L2CAP pdu, unsigned int longitud)
  222. {
  223.     int res;
  224.     unsigned int n, tipocomando;
  225.  
  226.     // Comprobamos que realmente se ha recibido una trama de control
  227.   if (!(*(pdu+2)==0x01)&(*(pdu+3)==0x00))  
  228.   {
  229.     cout<<"Esperado trama-C. Entrada no valida."<<endl;
  230.     return 1;
  231.   }
  232.     cout<<"Efectivamente era una trama de control. Ya estamos en el CANAL."<<endl;
  233.  
  234.    
  235.     n = 4;
  236.  
  237.        _receivedIdentifier = *(pdu+5); // de momento, sin considerar varios comandos en 1 trama-C
  238.  
  239.        tipocomando = *(pdu+n);
  240.        switch (tipocomando)
  241.        {
  242.               case L2CAP_CONREQ:
  243.                    {
  244.                     leerL2CAPcon_req(pdu,n);
  245.                     break;
  246.                    }
  247.                    
  248.               case L2CAP_CONRES:
  249.                    {
  250.                     res = leerL2CAPcon_res(pdu,n);
  251.                     break;
  252.                    }
  253.               default :
  254.                       {
  255.                            cout <<"Comando no valido."<<endl;
  256.                            return 2;
  257.                            break;
  258.                       }
  259.        }    
  260.        situacion ();
  261.    return 0;
  262. }
  263.  
  264.  
  265. void L2capChannel::situacion ()
  266. // Saca por pantalla el estado en el que nos encontramos
  267. {
  268.    switch (_estado)
  269.    {
  270.    case CLOSED :
  271.         {
  272.                printf("\t \t Estado = CLOSED \n \n");
  273.                break;
  274.         }
  275.    case WAIT_CONNECT :
  276.         {
  277.                printf("\t \t Estado = WAIT_CONNECT \n \n");
  278.                break;
  279.         }
  280.    case WAIT_CONNECT_RSP :
  281.         {
  282.                printf("\t \t Estado = WAIT_CONNECT_RSP \n \n");
  283.                break;
  284.         }
  285.    case OPEN :
  286.         {
  287.                printf("\t \t Estado = OPEN \n \n");
  288.                break;
  289.         }
  290.    case WAIT_DISCONNECT :
  291.         {
  292.                printf("\t \t Estado = WAIT_DISCONNECT \n \n");
  293.                break;
  294.         }
  295.    case WAIT_CONFIG :
  296.         {
  297.                printf("\t \t Estado = WAIT_CONFIG \n \n");
  298.                break;
  299.         }
  300.    case WAIT_SEND_CONFIG :
  301.         {
  302.                printf("\t \t Estado = WAIT_SEND_CONFIG \n \n");
  303.                break;
  304.         }
  305.    case WAIT_CONFIG_REQ_RSP :
  306.         {
  307.                printf("\t \t Estado = WAIT_CONFIG_REQ_RSP \n \n");
  308.                break;
  309.         }
  310.    case WAIT_CONFIG_RSP :
  311.         {
  312.                printf("\t \t Estado = WAIT_CONFIG_RSP \n \n");
  313.                break;
  314.         }
  315.    case WAIT_CONFIG_REQ :
  316.         {
  317.                printf("\t \t Estado = WAIT_CONFIG_REQ \n \n");
  318.                break;
  319.         }
  320.    default :
  321.            {
  322.            }
  323.    }
  324. }
  325.  
  326.  
  327. string L2capChannel::arrayToString(Tpdu_L2CAP a)
  328. {
  329.     unsigned int longitud,num,cal;
  330.  
  331.     longitud = *(a) + (*(a+1))*256;
  332.    
  333.     string result = "";
  334.  
  335.     for (int i=0; i<longitud; i++)
  336.     {
  337.       num = a[i];
  338.         if (Esnumero(char((num/16)+'0')))
  339.         {
  340.           result = result + char((num/16)+'0');
  341.         }
  342.         else
  343.         {
  344.            result = result + char((num/16)+'A'-10);  
  345.         }
  346.         cal=(num-(num/16)*16);
  347.         if (Esnumero(char( cal+'0')))
  348.         {
  349.           result = result + char(cal+'0');
  350.         }
  351.         else
  352.         {
  353.            result = result + char(cal+'A'-10);  
  354.         }
  355.     }
  356.     return result;
  357. }
  358.  
  359.  
  360. bool L2capChannel::Esnumero (char valor)
  361. {
  362.      bool test;
  363.      
  364.      switch (valor)
  365.      {
  366.             case '1':
  367.             case '2':
  368.             case '3':
  369.             case '4':
  370.             case '5':
  371.             case '6':
  372.             case '7':
  373.             case '8':
  374.             case '9':
  375.             case '0':
  376.                  {
  377.                      test = true;
  378.                      break;
  379.                  }
  380.             default :
  381.                     {
  382.                           test = false;
  383.                           break;
  384.                     }
  385.      }
  386.      return test;
  387. }
  388.  
  389.  
  390.  
  391. void L2capChannel::sendComando (unsigned int tipocomando)
  392. {
  393.      string cad;
  394.      Tpdu_L2CAP dataout ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};  
  395.  
  396.      printf("\n Se va a enviar a continuacion una PDU de contenido: \n");
  397.    switch (tipocomando)  
  398.     {                            
  399.     case L2CAP_CONREQ :    //0x02
  400.           {
  401.           vuelcaL2CAPcon_req(dataout);
  402.           imprimeArray (dataout,L2CAPcon_req_TX.Length + 8);
  403.           break;
  404.            }
  405.  
  406.     case L2CAP_CONRES :    //0x03
  407.           {
  408.           vuelcaL2CAPcon_res(dataout);
  409.           imprimeArray (dataout,L2CAPcon_res_TX.Length + 8);          
  410.           break;
  411.           }
  412.     default : {
  413.                     printf("Error. Campo Codigo incorrecto en SendComando \n");
  414.           }
  415.     }
  416.    
  417.     cad = arrayToString(dataout);
  418.         cout<<"Se va a enviar por el socket una PDU de contenido: "<<cad<<endl;
  419.  
  420. //        sockCanal->SendBytes(cad); // Canal manda mensaje por socket, si pasasemos el puntero a socket en el constructor
  421.  
  422. //    pt2Func (_ME,cad); // Llama al Wrapper y éste deberia escribir, pero no lo hace
  423.          
  424. } //SendComando
  425.  
  426.  
  427. // ********FUNCIONES DE VOLCADO DE DATOS DESDE LAS VARIABLES REGISTRO********
  428. //  ******************** AL ARRAY DE SALIDA (PDU)****************************
  429. void L2capChannel::vuelcaL2CAPcon_req(Tpdu_L2CAP &dataout)
  430. {
  431.      unsigned int longitud,ind,res,coc;
  432.      
  433.      longitud = L2CAPcon_req_TX.Length;
  434.      coc = longitud + 4;
  435.      for (ind=0;(ind<2);ind++)
  436.      {
  437.          res = coc % 256;
  438.          *(dataout+ind) = res;
  439.          coc = coc / 256;
  440.      }
  441.  
  442.      *(dataout+ind) = 0x1;     // trama de control
  443.      ind++;
  444.      *(dataout+ind) = 0x0;    
  445.      ind++;;
  446.          
  447.      *(dataout+ind) = L2CAPcon_req_TX.Code;
  448.      ind++;
  449.  
  450.      *(dataout+ind)= L2CAPcon_req_TX.ID;
  451.      ind++;
  452.  
  453.  
  454.      coc = L2CAPcon_req_TX.Length;
  455.  
  456.      for (ind=6;(ind<8);ind++)
  457.      {
  458.          res = coc % 256;
  459.          *(dataout+ind) = res;
  460.          coc = coc / 256;
  461.      }
  462.      
  463.      coc = L2CAPcon_req_TX.PSM;
  464.  
  465.      for (ind=8;(ind<10);ind++)
  466.      {
  467.          res = coc % 256;
  468.          *(dataout+ind) = res;
  469.          coc = coc / 256;
  470.      }
  471.  
  472.      coc = L2CAPcon_req_TX.SCID;
  473.  
  474.      for (ind=10;(ind<12);ind++)
  475.      {
  476.          res = coc % 256;
  477.          *(dataout+ind) = res;
  478.          coc = coc / 256;
  479.      }
  480. }
  481.  
  482.  
  483.  
  484. void L2capChannel::vuelcaL2CAPcon_res(Tpdu_L2CAP &dataout)
  485. {
  486.      unsigned int longitud,ind,res,coc;
  487.      
  488.      longitud = L2CAPcon_res_TX.Length;
  489.      coc = longitud + 4;
  490.  
  491.      for (ind=0;(ind<2);ind++)
  492.      {
  493.          res = coc % 256;
  494.          *(dataout+ind) = res;
  495.          coc = coc / 256;
  496.      }
  497.  
  498.      *(dataout+ind) = 0x1;     // trama de control
  499.      ind++;
  500.      *(dataout+ind) = 0x0;    
  501.      ind++;;
  502.      
  503.      
  504.      *(dataout+ind) = L2CAPcon_res_TX.Code;
  505.      ind++;
  506.  
  507.      *(dataout+ind)= L2CAPcon_res_TX.ID;
  508.      ind++;
  509.  
  510.  
  511.      coc = L2CAPcon_res_TX.Length;
  512.  
  513.      for (ind=6;(ind<8);ind++)
  514.      {
  515.          res = coc % 256;
  516.          *(dataout+ind) = res;
  517.          coc = coc / 256;
  518.      }
  519.  
  520.  
  521.      coc = L2CAPcon_res_TX.DCID;
  522.  
  523.      for (ind=8;(ind<10);ind++)
  524.      {
  525.          res = coc % 256;
  526.          *(dataout+ind) = res;
  527.          coc = coc / 256;
  528.      }
  529.  
  530.      
  531.      coc = L2CAPcon_res_TX.SCID;
  532.  
  533.      for (ind=10;(ind<12);ind++)
  534.      {
  535.          res = coc % 256;
  536.          *(dataout+ind) = res;
  537.          coc = coc / 256;
  538.      }
  539.  
  540.      coc = L2CAPcon_res_TX.Result;
  541.  
  542.      for (ind=12;(ind<14);ind++)
  543.      {
  544.          res = coc % 256;
  545.          *(dataout+ind) = res;
  546.          coc = coc / 256;
  547.      }
  548.  
  549.      coc = L2CAPcon_res_TX.Status;
  550.  
  551.      for (ind=14;(ind<(longitud+8));ind++)
  552.      {
  553.          res = coc % 256;
  554.          *(dataout+ind) = res;
  555.          coc = coc / 256;
  556.      }
  557. }
  558.  
  559.  
  560.  
  561. int L2capChannel::connectChannel()
  562. {
  563.  cout<<endl<<endl<<"Creando CANAL"<<endl<<endl;
  564.     if (_estado == CLOSED)
  565.     {
  566.         srand(time(NULL));
  567.         _identifier=rand();
  568.  
  569.         escribeL2CAPcon_req_TX ();
  570.         sendComando (L2CAP_CONREQ);
  571.  
  572.         _estado = WAIT_CONNECT_RSP;
  573.         return 0;
  574.     }
  575.     else
  576.     {
  577.         cout<<"Apertura canal no valida. Estado no CLOSED."<<endl;
  578.         return 1;
  579.     }
  580. }
  581.  
  582.  

 :ayuda:

33
C/C++ / Re: Comunicación Por Sockets
« en: Domingo 2 de Diciembre de 2007, 14:08 »
Buenos dias. Últimamente todo son problemas en el trabajo que estoy programando, y no acabo de salir de uno cuando me encuentro en otro todavía mas grande.

Antes de nada darle las gracias a Eternal Idol, por todas las respuestas y ayudas en los posts que he ido posteando estos dias atrás, y que sin duda me han ayudado a seguir adelante. Muchísimas gracias.


Mi programa, se distribuye en varias partes. El objetivo es implementar una capa de protocolo, y para ello, he hecho uso de las clases.

Mi clase L2cap, es la clase de mi capa que quiero implementar. Y dentro de ella, se hace uso de otra clase, que es la clase L2capChannel. Cuando dos instancias de L2cap establecen una comunicación entre ellas, crean un canal L2capChannel, y establecen una comunicación por socket.

Para los sockets he usado una clase que ya había implementada. Con lo cual hago uso de ella para dicha comunicación.


Los sockets los tengo en la clase L2cap, y cuando envío o recibo datos desde L2cap funciona sin problema aparente. (Es decir, si desde L2cap hago una llamada a sendRaw por ejemplo, se transmite el mensaje creado en sendRaw por el socket y llega a la otra entidad de mi programa).


La cosa es que yo necesito también que el L2capChannel, en algún momento determinado, como por ejemplo cuando reciba un mensaje de datos que sea una ConnectionRequest, deba enviar él otro mensaje que sea una ConnectionResponse. Y por tanto, para dicho envío, ha de hacer uso de los sockets. Por lo tanto, el canal debería de poder también enviar por el socket.


Primeramente pensé en pasarle en el constructor de L2capChannel, un puntero al socket. De manera que pudiese escribir din problemas. Sin embargo no funciona. Y no se por qué, porque revisé todo y debería de haber funcionado.

Otra alternativa que pensé fue en hacerlo mediante callbacks, que es la que actualmente tengo implementada (el constructor de L2capChannel en el caso de pasarle el puntero a socket lo tengo entre comentarios, y ahora solo uso el de callback). Sin embargo el resultado es el mismo.




Y ya no se que mas puedo hacer. He intentado hacerlo de todas las maneras posibles, pero llevo semanas atascado en dicha comunicación y no hay manera.  :(


La ejecución del programa ha de hacerse de la siguiente manera:
Primero ejecuto, y elijo la opción 1, que es el modo Servidor. De esa manera habrá alguien escuchando en el puerto.

Seguidamente, ejecuto el programa de nuevo, dejando el otro abierto, y ésta vez, elegimos la opción 2, que es el modo cliente. Ésto provocará que a la hora de crear mi nueva capa L2cap lo haga de forma diferente (como cliente).
Y después de crear mi capa, llama a la primitiva de L2cap OpenChannelReq.


Tanto en el caso del Servidor como del Cliente, he colocado un bucle infinito para que no finalice la ejecución del programa, y en dicho bucle saca un mensaje por pantalla.



OpenChannel se encarga de abrir un nuevo canal para una comunicación. Para ello busca un CID (identificador de canal) libre, y crea un nuevo L2capChannel, introduciéndolo en el vector de canales, y construyendo dicho canal mandándole mediante callback la funcion que usará el canal para enviar datos por el socket (ya que el socket está en L2cap y no en L2capChannel).



Seguidamente actualiza también el vector tabla, que es simplemente un registro de los canales que han sido creados en mi capa L2cap.

Y finalmente, se hace una llamada a ese canal creado en el vector, a su procedimiento connectChannel().

[connect channel, provocaría la elaboración de una Connection Request, la almacenaria en variables globales, pasaría dichas variables a un array de salida, crearia una string con el contenido a mandar, y la tendría que mandar por el socket]

Sin embargo, en lugar de toda esta secuencia de acciones, para testear la comunicación por el socket, en el mismo constructor del canal L2capChannel, he puesto que se llame al Wrapper a la función que escribe en el socket en L2cap. He puesto que escriba una cadena de caracteres, que resulta que es una ConnectionRequest.

La llamada al Wrapper se realiza perfectamente, ya que se muestra por pantalla que se ha entrado en dicha función.

Pero por el socket no se escribe nada. El Servidor debería de recibir la cadena por el socket, y no la recibe.

El cliente muestra que se ha creado un canal, muestra el contenido de la tabla, y dice que ha enviado por el socket una cadena, pero al Servidor no le llega.


Se que quizás sea muy extenso el código, he intentado reducirlo al máximo dejando solo lo indispensable para ver el problema de la comunicación por socket.
Muchísimas gracias por todo.

Pongo el código a continuación de cada uno de los archivos, comenzando por la clase Socket, seguida de los archivos de mi programa.

Muchas gracias.

-----------------------------|  socket.h  |--------------------

Código: Text
  1. #ifndef SOCKET_H
  2. #define SOCKET_H
  3.  
  4. #include <C:\Dev-Cpp\include\WinSock2.h>
  5. #include <string>
  6.  
  7. enum TypeSocket {BlockingSocket, NonBlockingSocket};
  8.  
  9. class Socket {
  10.     public:
  11.     
  12.       virtual ~Socket();
  13.       Socket(const Socket&);
  14.       Socket& operator=(Socket&);
  15.     
  16.       std::string ReceiveLine();
  17.       std::string ReceiveBytes();
  18.     
  19.       void   Close();
  20.     
  21.       // The parameter of SendLine is not a const reference
  22.       // because SendLine modifes the std::string passed.
  23.       void   SendLine (std::string);
  24.     
  25.       // The parameter of SendBytes is a const reference
  26.       // because SendBytes does not modify the std::string passed
  27.       // (in contrast to SendLine).
  28.       void   SendBytes(const std::string&);
  29.     
  30.     protected:
  31.       friend class SocketServer;
  32.       friend class SocketSelect;
  33.     
  34.       Socket(SOCKET s);
  35.       Socket();
  36.     
  37.     
  38.       SOCKET s_;
  39.     
  40.       int* refCounter_;
  41.     
  42.     private:
  43.       static void Start();
  44.       static void End();
  45.       static int  nofSockets_;
  46.  
  47. };
  48.  
  49.  
  50. class SocketClient : public Socket
  51. {
  52.     public:
  53.       SocketClient(const std::string& host, int port);
  54. };
  55.  
  56.  
  57.  
  58. class SocketServer : public Socket
  59. {
  60.     public:
  61.       SocketServer(int port, int connections, TypeSocket type=BlockingSocket);
  62.     
  63.       Socket* Accept();
  64. };
  65.  
  66.  
  67. // http: //msdn.microsoft .com/library/default.asp?url=/library/en-us/winsock/wsapiref_2tiq.asp
  68. class SocketSelect {
  69.   public:
  70.     SocketSelect(Socket const * const s1, Socket const * const s2=NULL, TypeSocket type=BlockingSocket);
  71.  
  72.     bool Readable(Socket const * const s);
  73.  
  74.   private:
  75.     fd_set fds_;
  76. };
  77.  
  78.  
  79. #endif
  80.  
  81.  


-----------------------------|  socket.cpp  |--------------------
Código: Text
  1. #include <SOCKET.h>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6.  
  7. int Socket::nofSockets_= 0;
  8.  
  9.  
  10. void Socket::Start()
  11. {
  12.   if (!nofSockets_)
  13.   {
  14.     WSADATA info;
  15.     if (WSAStartup(MAKEWORD(2,0), &info))
  16.     {
  17.       throw "Could not start WSA";
  18.     }
  19.   }
  20.   ++nofSockets_;
  21. }
  22.  
  23.  
  24. void Socket::End()
  25. {
  26.   WSACleanup();
  27. }
  28.  
  29.  
  30. Socket::Socket() : s_(0)
  31. {
  32.   Start();
  33.   // UDP: use SOCK_DGRAM instead of SOCK_STREAM
  34.   s_ = socket(AF_INET,SOCK_STREAM,0);
  35.  
  36.   if (s_ == INVALID_SOCKET)
  37.   {
  38.     throw "INVALID_SOCKET";
  39.   }
  40.  
  41.   refCounter_ = new int(1);
  42. }
  43.  
  44.  
  45. Socket::Socket(SOCKET s) : s_(s)
  46. {
  47.   Start();
  48.   refCounter_ = new int(1);
  49. };
  50.  
  51.  
  52. Socket::~Socket()
  53. {
  54.   if (! --(*refCounter_))
  55.   {
  56.     Close();
  57.     delete refCounter_;
  58.   }
  59.  
  60.   --nofSockets_;
  61.   if (!nofSockets_) End();
  62. }
  63.  
  64.  
  65. Socket::Socket(const Socket& o)
  66. {
  67.   refCounter_=o.refCounter_;
  68.   (*refCounter_)++;
  69.   s_         =o.s_;
  70.  
  71.   nofSockets_++;
  72. }
  73.  
  74.  
  75. Socket& Socket::operator=(Socket& o)
  76. {
  77.   (*o.refCounter_)++;
  78.  
  79.   refCounter_=o.refCounter_;
  80.   s_         =o.s_;
  81.  
  82.   nofSockets_++;
  83.  
  84.   return *this;
  85. }
  86.  
  87.  
  88. void Socket::Close()
  89. {
  90.   closesocket(s_);
  91. }
  92.  
  93.  
  94. std::string Socket::ReceiveBytes()
  95. {
  96.   std::string ret;
  97.   char buf[1024];
  98.  
  99.   while (1) {
  100.     u_long arg = 0;
  101.     if (ioctlsocket(s_, FIONREAD, &arg) != 0)
  102.     {
  103.       break;
  104.     }
  105.  
  106.     if (arg == 0)
  107.     {
  108.       break;
  109.     }
  110.     
  111.     if (arg > 1024)
  112.     {
  113.             arg = 1024;
  114.     }
  115.  
  116.     int rv = recv (s_, buf, arg, 0);
  117.  
  118.     if (rv <= 0)
  119.     {
  120.            break;
  121.     }
  122.  
  123.     std::string t;
  124.  
  125.     t.assign (buf, rv);
  126.     ret += t;
  127.   }
  128.  
  129.   return ret;
  130. }
  131.  
  132.  
  133. std::string Socket::ReceiveLine()
  134. {
  135.   std::string ret;
  136.   while (1)
  137.   {
  138.     char r;
  139.  
  140.     switch(recv(s_, &r, 1, 0))
  141.     {
  142.       case 0: // not connected anymore;
  143.               // ... but last line sent
  144.               // might not end in \n,
  145.               // so return ret anyway.
  146.         return ret;
  147.  
  148.       case -1:
  149.         return "";
  150. //      if (errno == EAGAIN) {
  151. //        return ret;
  152. //      } else {
  153. //      // not connected anymore
  154. //      return "";
  155. //      }
  156.     }
  157.  
  158.     ret += r;
  159.     if (r == '\n')  return ret;
  160.   }
  161. }
  162.  
  163.  
  164. void Socket::SendLine(std::string s)
  165. {
  166.   s += '\n';
  167.   send(s_,s.c_str(),s.length(),0);
  168. }
  169.  
  170.  
  171. void Socket::SendBytes(const std::string& s)
  172. {
  173.   send(s_,s.c_str(),s.length(),0);
  174. }
  175.  
  176.  
  177. SocketServer::SocketServer(int port, int connections, TypeSocket type)
  178. {
  179.   sockaddr_in sa;
  180.  
  181.   memset(&sa, 0, sizeof(sa));
  182.  
  183.   sa.sin_family = PF_INET;            
  184.   sa.sin_port = htons(port);          
  185.   s_ = socket(AF_INET, SOCK_STREAM, 0);
  186.   if (s_ == INVALID_SOCKET)
  187.   {
  188.     throw "INVALID_SOCKET";
  189.   }
  190.  
  191.   if(type==NonBlockingSocket)
  192.   {
  193.     u_long arg = 1;
  194.     ioctlsocket(s_, FIONBIO, &arg);
  195.   }
  196.  
  197.   /* bind the socket to the internet address */
  198.   if (bind(s_, (sockaddr *)&sa, sizeof(sockaddr_in)) == SOCKET_ERROR)
  199.   {
  200.     closesocket(s_);
  201.     throw "INVALID_SOCKET";
  202.   }
  203.   
  204.   listen(s_, connections);                              
  205. }
  206.  
  207.  
  208. Socket* SocketServer::Accept()
  209. {
  210.   SOCKET new_sock = accept(s_, 0, 0);
  211.   if (new_sock == INVALID_SOCKET)
  212.   {
  213.     int rc = WSAGetLastError();
  214.     if(rc==WSAEWOULDBLOCK)
  215.     {
  216.       return 0; // non-blocking call, no request pending
  217.     }
  218.     else
  219.     {
  220.       throw "Invalid Socket";
  221.     }
  222.   }
  223.  
  224.   Socket* r = new Socket(new_sock);
  225.   return r;
  226. }
  227.  
  228.  
  229. SocketClient::SocketClient(const std::string& host, int port) : Socket()
  230. {
  231.   std::string error;
  232.  
  233.   hostent *he;
  234.   if ((he = gethostbyname(host.c_str())) == 0)
  235.   {
  236.     error = strerror(errno);
  237.     throw error;
  238.   }
  239.  
  240.   sockaddr_in addr;
  241.   addr.sin_family = AF_INET;
  242.   addr.sin_port = htons(port);
  243.   addr.sin_addr = *((in_addr *)he->h_addr);
  244.   memset(&(addr.sin_zero), 0, 8);
  245.  
  246.   if (::connect(s_, (sockaddr *) &addr, sizeof(sockaddr)))
  247.   {
  248.     error = strerror(WSAGetLastError());
  249.     throw error;
  250.   }
  251. }
  252.  
  253.  
  254. SocketSelect::SocketSelect(Socket const * const s1, Socket const * const s2, TypeSocket type)
  255. {
  256.   FD_ZERO(&fds_);
  257.   FD_SET(const_cast<Socket*>(s1)->s_,&fds_);
  258.   if(s2)
  259.   {
  260.     FD_SET(const_cast<Socket*>(s2)->s_,&fds_);
  261.   }    
  262.  
  263.   TIMEVAL tval;
  264.   tval.tv_sec  = 0;
  265.   tval.tv_usec = 1;
  266.  
  267.   TIMEVAL *ptval;
  268.   if(type==NonBlockingSocket)
  269.   {
  270.     ptval = &tval;
  271.   }
  272.   else
  273.   {
  274.     ptval = 0;
  275.   }
  276.  
  277.   if (select (0, &fds_, (fd_set*) 0, (fd_set*) 0, ptval) == SOCKET_ERROR)
  278.     throw "Error in select";
  279. }
  280.  
  281. bool SocketSelect::Readable(Socket const* const s)
  282. {
  283.   if (FD_ISSET(s->s_,&fds_)) return true;
  284.   return false;
  285. }
  286.  
  287.  


-----------------------------|  tipos.h  |--------------------
Código: Text
  1. //                              DEFINICION DE TIPOS
  2.  
  3. typedef unsigned int Tpdu_L2CAP [1200]; // Dato de entrada, PDU L2CAP  
  4.  
  5.  
  6.  
  7. typedef struct {
  8.   unsigned int Code;
  9.   unsigned int ID;
  10.   int Length;
  11.   int PSM;
  12.   int SCID;
  13. } TL2CAP_con_req;    // Connection Request packet
  14.  
  15. typedef struct {
  16.   unsigned int Code;
  17.   unsigned int ID;
  18.   int Length;
  19.   int DCID;
  20.   int SCID;
  21.   int Result;
  22.   int Status;
  23. } TL2CAP_con_res;   // Connection Response packet
  24.  
  25.  

-----------------------------|  constantes.h  |--------------------
Código: Text
  1. // Codigos de los comandos de señalizacion
  2.  
  3. #define L2CAP_CONREQ 0x02
  4. #define L2CAP_CONRES 0x03
  5.  
  6.  
  7. // Estados definidos en la máquina de estados
  8.  
  9. #define CLOSED 0x00
  10. #define WAIT_CONNECT 0x01
  11. #define WAIT_CONNECT_RSP 0x02
  12. #define CONFIG 0x03   // Consta de un numero de sub estados
  13. #define OPEN 0x04
  14. #define WAIT_DISCONNECT 0x05
  15.  
  16. // Sub estados dentro del estado CONFIG
  17.  
  18. #define WAIT_CONFIG 0x06
  19. #define WAIT_SEND_CONFIG 0x07
  20. #define WAIT_CONFIG_REQ_RSP 0x08
  21. #define WAIT_CONFIG_RSP 0x09
  22. #define WAIT_CONFIG_REQ 0x10
  23.  
  24. // Eventos
  25.  
  26. #define OPENCHANNEL_REQ 0x01
  27. #define OPENCHANNEL_RSP 0x02
  28. #define CONNECTREQ 0x03
  29. #define CONNECTRSP 0x04
  30.  
  31.  


-----------------------------|  principal.cpp  |--------------------
Código: Text
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <L2cap.h>
  4. #include <windows.h>
  5.  
  6. using namespace std;
  7.  
  8.  
  9. int main()
  10. {
  11.   int msg,opcion;
  12.   std::string cadena;
  13.     msg = 0;
  14.     
  15.     do
  16.   {
  17.     system("cls");
  18.     opcion = 0;
  19.     cout <<endl<<"                *-----------------------------------------*";
  20.     cout <<endl<<"                |        B  L  U  E  T  O  O  T  H        |";
  21.     cout <<endl<<"                *-----------------------------------------*";
  22.     cout <<endl<<"                |       M E N U   L 2 C A P   v 2.1.      |";
  23.     cout <<endl<<"                *-----------------------------------------*";
  24.     cout <<endl<<"                |                                         |";
  25.     cout <<endl<<"                |  1.- Modo Servidor................. (1) |";
  26.     cout <<endl<<"                |  2.- Modo Cliente manda PDU........ (2) |";
  27.         cout <<endl<<"                |  3.- Salir......................... (3) |";
  28.     cout <<endl<<"                |                                         |";
  29.     cout <<endl<<"                *-----------------------------------------*"<<endl<<endl<<endl;
  30.     cout <<endl<<"                  >  Elija una Opcion.......... ";
  31.     scanf("%d",&opcion);
  32.  
  33.   }while (opcion < 1 || opcion > 3);
  34.  
  35.   //Lee Menu y llama funciones
  36.   switch(opcion)
  37.     {            
  38.          case 1:
  39.              {
  40.               system("cls");
  41.               L2cap micapa(1);
  42.               while (1)
  43.               {
  44.                     cout<<"Sigo aqui en modo Servidor..."<<endl;
  45.                     Sleep(4000);  
  46.                 }
  47.                 break;
  48.              }
  49.  
  50.          case 2:
  51.              {
  52.               system("cls");
  53.               L2cap micapa(2);
  54.                 
  55.                 micapa.Openchannel_req ();
  56.                 
  57.                 //micapa.sendRaw();  
  58.                 // Si utilizo sendRaw desde aquí, SI funciona la comunicación
  59.                 //por Socket de client a Serv, pero no de Serv a cliente (el canal no escribe por socket)
  60.                 
  61.                 while (1)
  62.                 {
  63.                    cout<<"Sigo aqui en modo Cliente..."<<endl;
  64.                    Sleep(4000);  
  65.                  }
  66.               system("pause");
  67.               break;
  68.              }
  69.     
  70.         case 3:
  71.             {
  72.                 system("cls");
  73.               L2cap micapa(3);                
  74.                 micapa.Salir();
  75.                 cout <<endl<<"                >  FIN DEL PROGRAMA.........."<<endl<<endl;
  76.             break;
  77.         }
  78.     }
  79.   return 0;
  80. }  
  81.  
  82.  


-----------------------------|  l2cap.h  |--------------------
Código: Text
  1. //#include <Socket.h>
  2. #include <L2capChannel.h>
  3. #include <vector>
  4. #include <string>
  5. #include <sstream>
  6. #include <iostream>
  7. #include <cstdlib>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10.  
  11. using namespace std;
  12.  
  13.  
  14.                    // DEFINICION DE TIPOS
  15.  
  16. typedef struct
  17. {
  18.     unsigned int CID;
  19.   unsigned int PSM;
  20.   int funcptr;
  21. } Ttabla;
  22.  
  23.  
  24. typedef L2capChannel *Tpcanal;
  25.  
  26.  
  27.  
  28. class L2cap
  29. {
  30.  
  31.  public:
  32.         
  33.      L2cap (int mode);  // Constructor.
  34.      ~L2cap (); // Destructor.
  35.      void Salir ();    
  36.      void Send_Data(std::string cadena); // Modo Cliente        
  37.      void Server(int argc, char* argv[]); // Modo Servidor
  38.      void leerSocketClient();
  39.      void leerSocketServer();
  40.      void leerSocket();
  41.      void sendRaw();
  42.      bool escuchando();
  43.  
  44.      void escribeEnSocket(std::string cadena);
  45.      static void Wrapper_a_escribeEnSocket (void* pt2Object, std::string cadena);
  46.  
  47.  
  48.      int Openchannel_req ();
  49.  
  50.  
  51.  private:    
  52.                        // VARIABLES GLOBALES
  53.      Socket *s;
  54.      bool _escuchando;
  55.      vector<Ttabla> tabla;
  56.      vector<L2capChannel*> canales;
  57.     
  58.       
  59.                          //     FUNCIONES
  60.  
  61.         void string_to_bytearray (std::string str, unsigned int* &array, int& size);
  62.  
  63.         unsigned int Leertipotrama (Tpdu_L2CAP datain);
  64.         static unsigned __stdcall bucleLectura(void* a);
  65.         void Analiza_contenido(std::string r);
  66.         int BuscaTabla(int cid);
  67.         void ImprimeTabla();
  68.         int AsignaCID(void);
  69. };
  70.  
  71.  


-----------------------------|  l2cap.cpp  |--------------------
Código: Text
  1. #include <L2cap.h>
  2. #include <Socket.h>
  3. #include <vector>
  4. #include <process.h>
  5. #include <string>
  6. #include <sstream>
  7. #include <iostream>
  8. #include <cstdlib>
  9. #include <stdio.h>
  10.  
  11. using namespace std;
  12.  
  13.  
  14. bool L2cap::escuchando()
  15. {
  16.      return _escuchando;
  17. }
  18.  
  19.  
  20. unsigned __stdcall L2cap::bucleLectura(void* a)
  21. {
  22.   L2cap *thisL2cap = (L2cap*)a;
  23.     
  24.   while (thisL2cap->escuchando())
  25.   {
  26.     cout<<endl<<"Esperando Nuevos datos..."<<endl;
  27.     thisL2cap->leerSocket();
  28.   }
  29.   return 0;
  30. }
  31.  
  32.  
  33. L2cap::L2cap (int mode)  // Constructor
  34. {
  35.    _escuchando = true;
  36.  
  37.    if (mode==1) // Modo Servidor
  38.    {
  39.    SocketServer in(3000,5);
  40.    Socket* sa=in.Accept();
  41.    s = sa;
  42.    cout<<"Conexion Recibida"<<endl;      
  43.  
  44.    unsigned ret;
  45.    _beginthreadex(0,0,bucleLectura,(void*)this,0,&ret);
  46.    }
  47.  
  48.    else if (mode==2) // Modo Cliente
  49.    {
  50.    SocketClient sb("pc.", 3000);
  51.    s = &sb;
  52.    *(s) = sb; //Con esto hemos anclado el contenido del puntero y ya no se borra al salir del Constructor
  53.  
  54.  
  55.    unsigned ret;
  56.    _beginthreadex(0,0,bucleLectura,(void*)this,0,&ret);
  57.    }
  58. } //Ctor
  59.  
  60.  
  61.  
  62. L2cap::~L2cap ()  // Destructor
  63. {
  64. }
  65.  
  66.  
  67.  
  68. void L2cap::string_to_bytearray(std::string str, unsigned int* &array, int& size)
  69. {
  70.   int length = str.length();
  71.   // nos aseguramos de que la cadena entrante tiene un número de elementos par
  72.   if(length%2 == 1)
  73.   {
  74.     str = "0" + str;
  75.     length++;
  76.   }
  77.   // Reservamos memoria para el array de salida  
  78.   array = new unsigned int[length/2];
  79.   size = length/2;
  80.  
  81.   std::stringstream sstr(str);
  82.  
  83.   for(int i=0; i < size; i++)
  84.   {
  85.     char ch1, ch2;
  86.     sstr >> ch1 >> ch2;
  87.     unsigned int dig1, dig2;
  88.     if(isdigit(ch1)) dig1 = ch1 - '0';
  89.     else if(ch1>='A' && ch1<='F') dig1 = ch1 - 'A' + 10;
  90.     else if(ch1>='a' && ch1<='f') dig1 = ch1 - 'a' + 10;
  91.     if(isdigit(ch2)) dig2 = ch2 - '0';
  92.     else if(ch2>='A' && ch2<='F') dig2 = ch2 - 'A' + 10;
  93.     else if(ch2>='a' && ch2<='f') dig2 = ch2 - 'a' + 10;
  94.     array[i] = dig1*16 + dig2;
  95.   }
  96. }
  97.  
  98.  
  99.  
  100. unsigned int L2cap::Leertipotrama(Tpdu_L2CAP datain)    
  101. {
  102.   unsigned int tipo;
  103.  
  104.   if ((*(datain+2)==0x01)&(*(datain+3)==0x00))  
  105.   {
  106.     tipo = 'C'; // Trama de control. c-frame
  107.   }
  108.   else if ((*(datain+2)==0x02)&(*(datain+3)==0x00))
  109.   {
  110.     tipo = 'G'; // Trama G. Canal no orientado a conexión
  111.   }
  112.   else if ((*(datain+2)>=0x40))
  113.   {
  114.     tipo = 'B';  // Trama-B
  115.   }
  116.   else
  117.   {
  118.     tipo = 'N'; // Tipo no válido
  119.   }
  120.   return tipo;
  121. }
  122.  
  123.  
  124. void L2cap::Salir () // Funcion que manda por socket la cadena salir que hace que salga del bucle infinito Server
  125. {
  126.    int i;
  127.   
  128.    SocketClient s("pc.", 3000); //No hace falta crear el socket de nuevo
  129.    std::string c1 = "exit";
  130.    s.SendBytes(c1);
  131. }
  132.  
  133.  
  134. int L2cap::BuscaTabla(int cid)
  135. {
  136.     int bus=-1;
  137.     for (int i=0; i<tabla.size();i++)
  138.     {
  139.         if (tabla[i].CID==cid)
  140.         {
  141.            bus=i;
  142.         }
  143.     }
  144.     return bus;
  145.     //Si no ha encontrado registrado en la tabla el CID buscado, devuelve -1,
  146.     //En caso de q lo encuentre, devuelve la posicion en la que se encuentra el
  147.     //canal con dicho CID
  148. }
  149.  
  150.  
  151. void L2cap::ImprimeTabla()
  152. {
  153.     printf("\n\n----TABLA DE REGISTRO DE CANALES L2CAP----\n");
  154.     for (int i=0; i<tabla.size();i++)
  155.     {
  156.         printf("tabla [%d].CID = %X \n",i,tabla[i].CID);
  157.         printf("tabla [%d].PSM = %X \n\n",i,tabla[i].PSM);
  158.     }
  159. }
  160.  
  161.  
  162.  
  163. int L2cap::AsignaCID()
  164. //Busca, para una trama de datos (B), que CID hay libre para asignarle
  165. //a la comunicación actual
  166. {
  167.     int nuevoCID=0x40;
  168.     while (BuscaTabla(nuevoCID)>=0)
  169.     {
  170.           printf("Ya esta registrado el CID de valor %X \n",nuevoCID);
  171.           nuevoCID++;
  172.     }
  173.     printf("Registrado con exito el CID de valor %X \n",nuevoCID);
  174.     return nuevoCID; //Devuelve el 1ero que no esta en la tabla
  175. }
  176.  
  177.  
  178. void L2cap::Analiza_contenido(std::string r)
  179. {
  180.     unsigned int longitud, tipo;
  181.      unsigned int* datain = NULL;
  182.     int size,CID,bus,num;
  183.  
  184.     size = r.length();
  185.     if (size>0)
  186.     {  
  187.       if (r =="exit")
  188.       {
  189.           _escuchando = false;
  190.           cout<<"Escuchando se ha puesto a false"<<endl;
  191.       }
  192.       else
  193.       {
  194.           cout <<"Recibida una string de longitud "<<r.length()<<endl<<"y contenido: "<<r<<endl<<endl;                
  195.           string_to_bytearray(r,datain,size);
  196.           
  197.           longitud = size-4; // se trata del campo length, mientras q size es toda.
  198.         
  199.           tipo = Leertipotrama (datain);
  200.         
  201.           switch (tipo)
  202.             {
  203.             case 'C' :  // Se trata de una trama-C
  204.               {    
  205.                 printf("Es una trama C \n \n");
  206.                      // Primero vemos de que comando se trata
  207.                            int code = *(datain+4);
  208.                           
  209.                            if (code==L2CAP_CONREQ)
  210.                            {
  211.                              //Creamos un canal nuevo, actualizamos tabla,...
  212.                            int receivedPSM = *(datain+8) + (*(datain+9))*256;
  213.                              CID = AsignaCID(); //Asignamos nuevo CID
  214.                              cout<<"Recibida Connection Request"<<endl;
  215.  
  216.                              canales.push_back(new L2capChannel(CID,receivedPSM,s)); //puntero a socket
  217.                              Ttabla elementoTabla;
  218.                              elementoTabla.CID = CID;
  219.                              elementoTabla.PSM = receivedPSM;
  220.                              tabla.push_back(elementoTabla);
  221.                              ImprimeTabla();
  222.                            }
  223.                           
  224.                            else
  225.                            //Se trata de una: ConnectionRsp, ConfigReq,
  226.                            //ConfigRsp*, DiscReq
  227.                            {
  228.                                CID = *(datain+8) + (*(datain+9))*256;
  229.                            }
  230.                         
  231.                         bus=BuscaTabla(CID);
  232.                         if (bus >=0)
  233.                         {
  234.                            num=canales[bus]->entradaComandos(datain,longitud);
  235.                         }
  236.  
  237.                     break;
  238.                     }
  239.         
  240.             case 'G' :  // Se trata de una trama-G
  241.               {
  242.                     printf("Es una trama G \n \n");    
  243.               break;
  244.               }
  245.         
  246.             case 'B' : //Se trata de una trama-B
  247.               {
  248.                         printf("Es una trama B \n \n");
  249.                   break;
  250.               }
  251.                 
  252.                 case 'N':
  253.               {
  254.               printf("Trama no valida. \n \n");
  255.                   break;
  256.               }
  257.                 
  258.                 default :
  259.               {
  260.                 printf("Algo esta pasando... \n \n");
  261.               }
  262.                }        
  263.       }      
  264.     }
  265. }
  266.  
  267.  
  268.  
  269.  
  270. void L2cap::leerSocket()
  271. {
  272.      cout<<"Voy a leer"<<endl;
  273.  
  274.      std::string r = "";
  275.      while (r.length()==0)
  276.      {
  277.        r = s->ReceiveBytes();
  278.      }
  279.      Analiza_contenido(r);    
  280.      cout<<"Ya he leido"<<endl;
  281. }
  282.  
  283.  
  284.  
  285. void L2cap::sendRaw()
  286. {
  287.     std::string cadena="080001000205040001004000"; //Connection Request    
  288.     escribeEnSocket(cadena);
  289.     cout<<"He enviado una cadena"<<endl;
  290. }
  291.  
  292.  
  293. int L2cap::Openchannel_req ()
  294. {
  295.     int res = 0;
  296.     int PSM = 2;
  297.     int CID,bus,num;
  298.  
  299.      CID = AsignaCID();
  300.     
  301. // Metemos en el vector de canales un nuevo elemento Canal que creamos con su constructor
  302.  
  303. //     canales.push_back(new L2capChannel(CID,PSM,s)); // Puntero a socket
  304.      canales.push_back(new L2capChannel(CID,PSM,(void*)this,&Wrapper_a_escribeEnSocket)); // Callback
  305.     
  306.  
  307. // Metemos tambien los datos del canal que hemos creado para registrarlo en la tabla
  308.  
  309.      Ttabla elementoTabla;
  310.      elementoTabla.CID = CID;
  311.      elementoTabla.PSM = PSM;
  312.      tabla.push_back(elementoTabla);
  313.      ImprimeTabla();        
  314.  
  315.     bus=BuscaTabla(CID);
  316.     if (bus >=0)
  317.     {
  318.        num=canales[bus]->connectChannel(); // Llamamos a connectChannel dentro de L2capChannel
  319.     }
  320.     return res;
  321. }
  322.  
  323.  
  324. void L2cap::escribeEnSocket(std::string cadena)
  325. {
  326.      cout<<"Cadenita a mandar: "<<cadena<<endl;
  327.      s->SendBytes(cadena);
  328. }
  329.  
  330.  
  331.  
  332. void L2cap::Wrapper_a_escribeEnSocket (void* pt2Object, std::string cadena)
  333. {
  334.      cout<<"Welcome to WRAPPER"<<endl;
  335.        L2cap* mySelf = (L2cap*) pt2Object;
  336.        mySelf->escribeEnSocket(cadena);
  337.       
  338.       //mySelf->sendRaw();  // Esto debería de funcionar, pero tampoco
  339. }
  340.  
  341.  


-----------------------------|  l2capChannel.h  |--------------------
Código: Text
  1. #include <iostream>
  2. #include <string>
  3. #include <tipos.h>
  4. #include <constantes.h>
  5. #include <Socket.h>
  6.  
  7.  
  8. using namespace std;
  9.  
  10. class L2capChannel
  11. {
  12.  
  13.  
  14.  public:
  15.         
  16.          L2capChannel (int CID, int PSM,Socket* a);  // Constructor. Se encarga de la correcta inicializacion
  17.          L2capChannel (int CID, int PSM,void* a, void(*pt2Func)(void*, std::string));
  18.          ~L2capChannel ();
  19.          unsigned int Obtener_estado();
  20.  
  21.          int entradaComandos (Tpdu_L2CAP pdu, unsigned int longitud);
  22.          int connectChannel();
  23.         
  24.  private:        
  25.                        // VARIABLES GLOBALES
  26.  
  27.     unsigned int _estado; // Indica el estado en el que nos encontramos
  28.     unsigned int _leidos;
  29.     unsigned int _MTU_negociada;
  30.     unsigned int _MTU_sig; // de señalizacion
  31.     unsigned int _identifier, _receivedIdentifier;
  32.     int _localCID, _remoteCID, _PSM;
  33.     void* _ME;
  34.  
  35.     Socket* sockCanal;
  36.  
  37.  
  38.                       //Variables de cada tipo de comando
  39.  
  40.   TL2CAP_con_req L2CAPcon_req_TX, L2CAPcon_req_RX;
  41.   TL2CAP_con_res L2CAPcon_res_TX, L2CAPcon_res_RX;
  42.     
  43.  
  44.                          //     FUNCIONES
  45.     
  46.     void sendComando (unsigned int tipocomando);    
  47.     void imprimeArray (Tpdu_L2CAP datain, unsigned int longitud);
  48.  
  49.     
  50.                          // funciones de lectura de cada tipo de trama-C        
  51.         void leerL2CAPcon_req(Tpdu_L2CAP pdu, unsigned int &n);
  52.         int  leerL2CAPcon_res(Tpdu_L2CAP pdu, unsigned int &n);
  53.  
  54.         void imprimeComando (unsigned int codigo);
  55.     
  56.  
  57.     void escribeL2CAPcon_req_TX (void);
  58.     void escribeL2CAPcon_res_TX (int result);
  59.  
  60.     
  61.     void situacion ();
  62.         
  63.     void vuelcaL2CAPcon_req(Tpdu_L2CAP &dataout);
  64.     void vuelcaL2CAPcon_res(Tpdu_L2CAP &dataout);
  65.     
  66.     string arrayToString(Tpdu_L2CAP a);
  67.     bool Esnumero (char valor);
  68. };
  69.  
  70.  
  71.  

34
C/C++ / Re: Stl Vector De Punteros
« en: Domingo 2 de Diciembre de 2007, 11:45 »
Muchisimas gracias de nuevo EternalIdol.

35
C/C++ / Re: Stl Vector De Punteros
« en: Viernes 30 de Noviembre de 2007, 20:47 »
Saludos de nuevo. Iba a abrir un nuevo hilo, pero al tratarse de nuevo de procedimientos con la std vector y estar trabajando dentro de una clase creo que sería mejor postearlo aquí.

Bien. Yo dentro de mi clase, utilizo 2 elementos de tipo vector. Uno de ellos almacena punteros a elementos de otra clase, y el otro almacena simplemente un registro, en cada posición, y digamos que los dos están relacionados, y el segundo vector es como un 'registro' de lo que tengo almacenado en el primer vector (sus identificadores y demas..)

Bueno, el problema me ha surgido cuando he intentado eliminar un elemento del vector. (el elemento ha de ser eliminaod de ambos, y en ambos tengo el problema).

Creo que el problema aparece debido a que estoy utilizando la std vector dentro de una Clase.

La eliminación de un elemento, en un vector, se realizaría de la siguiente forma:

Código: Text
  1.  
  2.  
  3.   int posicion=5; //por ejemplo
  4.  
  5.   vector<int>::iterator itRemove = arNumbers.begin() + posicion;
  6.  
  7.   arNumbers.erase(itRemove);
  8.  
  9.  
  10.  
  11.  

El mensaje de error obtenido tras intentar realizar el procedimiento erase, es el siguiente:


Código: Text
  1.  
  2. conversion from '__gnu_cxx::__normal_iterator<L2capChannel**, std::vector<L2capChannel*, std allocator<L2capChannel*> > >' to non-scalar type '__gnu_cxx::__normal_iterator<int*, std::vector<int,std::allocator<int> > >' requested
  3.  
  4.  
  5. no matching function for call to 'std::vector<L2capChannel*,std::allocator<L2capChannel*> > ::erase(__gnu_cxx::__normal_iterator<int*,std::vector<int,std::allocator<int> > >&)'
  6.  
  7.  
  8.  candidates are: typename std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(__gnu_cxx::__normal_iterator<typename _Alloc::pointer, std::vector<_Tp, _Alloc> >) [with _Tp = L2capChannel*, _Alloc = std::allocator<L2capChannel*>]
  9.  
  10.  note C:\Dev-Cpp\include\c++\3.4.2\bits\vector.tcc:108                 typename std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(__gnu_cxx::__normal_iterator<typename _Alloc::pointer, std::vector<_Tp, _Alloc> >, __gnu_cxx::__normal_iterator<typename _Alloc::pointer, std::vector<_Tp, _Alloc> >) [with _Tp = L2capChannel*, _Alloc = std::allocator<L2capChannel*>]
  11.  
  12.  
  13.  


¿Que puedo hacer? :ayuda:

36
C/C++ / Re: Stl Vector De Punteros
« en: Jueves 22 de Noviembre de 2007, 14:43 »
Muchísimas gracias de nuevo Eternal Idol, por tu respuesta.  :)

Un saludo.

37
C/C++ / Stl Vector De Punteros
« en: Jueves 22 de Noviembre de 2007, 09:34 »
Quería utilizar la stl vector, en lugar de un array, para ir almacenando valores conforme voy necesitando, y no tener que usar un array reservando un número de posiciones y eso.
Los  vectores, con sus instrucciones push_back, size(), ... son bastante cómodos en ese aspecto.
Si lo que realizo es un vector de una variable normal, por decirlo de alguna manera, como un int, un registro con sus campos, ... no hay problema.

Código: Text
  1. vector <int> mivector;
  2.  
  3. mivector.push_back(3); //Almacena el valor 3 en el vector
  4.  
  5. tamaño = mivector.size(); //devuelve el tamaño que tiene actualmente
  6.  
  7.  
Cuando quiera acceder a un elemento en concreto de los que tiene almacenado el vector, puedo acceder a ellos mediante:

Código: Text
  1. elemento=mivector[indice];
  2.  
  3.  

Pero el problema me surge cuando lo que quiero almacenar en el vector no es una variable de ese tipo, sino que quiero almacenar punteros a una clase que tengo creada.
Mi programa va a ir creando nuevos elementos de dicha clase conforme lo va necesitando, y yo en mi vector quiero almacenar punteros a cada uno de los elementos de tipo clase que haya creado.

Ahora mi variable vector será:

Código: Text
  1. vector <*Tclase> mivector2;
  2.  
  3. *Tclase elementonuevo; // tendre que ir almacenando punteros a Tclase
  4. mivector2.push_back(elementonuevo);
  5.  
  6.  
y para trabajar con los métodos de mi clase, de uno de los elementos que tengo en el vector, tendré que hacer:

Código: Text
  1. mivector2[indice]->metododemiclase(parametro1, parametro2);
  2.  
  3.  
¿Es correcto el planteamiento? Es que no termino de tenerlo claro si las definiciones y los accesos a los  metodos de la clase se realizarían de esa manera.

Muchisimas gracias de antemano!  :)

38
C/C++ / Re: Problema Con _beginthreadex En Una Clase
« en: Jueves 8 de Noviembre de 2007, 16:19 »
Un millón de gracias Eternal Idol. Ya compila. Yo creo que todo va bien. Si el acceso a los elementos es como me has confirmado, entonces está perfecto :).

Llevaba atascado varias semanas en ese punto, y nadie había podido ayudarme.

Muchísimas gracias de nuevo!  :kicking:

39
C/C++ / Re: Problema Con _beginthreadex En Una Clase
« en: Jueves 8 de Noviembre de 2007, 15:51 »
Estoy usando devc++.

Sin embargo creo que había cometido algún error y se me había olvidado algún static en el código.

Parece que ahora funciona.

Para acceder a las variables y métodos de mi clase, lo único que tengo ue hacer es hacerlo mediante:

if (thisL2cap->escuchando);

por ejemplo, ¿no?

Y para acceder a los métodos de la clase socket, tendré que usar la variable socket creada en L2cap, por lo que el acceso deberá ser:

    std::string r = thisL2cap->s->ReceiveBytes();  

por ejemplo.


¿Está bien así?

40
C/C++ / Re: Problema Con _beginthreadex En Una Clase
« en: Jueves 8 de Noviembre de 2007, 14:54 »
Muchas gracias Eternal Idol.

He realizado las modificaciones correspondientes, pero obtengo un error en _beginthreadex.

In member function 'void L2cap:: Server(int,char**)'

argument of type 'unsigned int (L2cap:: )(void*) does not match 'unsigned int (*)(void*)'

Build error (L2cap.o) Error 1


 :(

41
C/C++ / Re: Problema Con _beginthreadex En Una Clase
« en: Jueves 8 de Noviembre de 2007, 00:31 »
Si pongo Answer como estátito cobtengo el error siguiente:

invalid use of member L2cap::escuchando in static member function  :(


He intentado aislar mi código, de manera que se pueda probar a compilar el código aquí escrito. Ya que si pongo solo partes del código no podemos probar a compilar quizás y no damos con la solución quizás.

El código completo de la clase l2cap, tanto el h como el cpp es el siguiente:

l2cap.h

Código: Text
  1. #include <Socket.h>
  2. #include <string>
  3. #include <sstream>
  4. #include <iostream>
  5. #include <cstdlib>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9.  
  10. class L2cap
  11. {
  12.  
  13.  public:
  14.         
  15.      L2cap ();
  16.      void Conecta(); // Modo Cliente        
  17.      void Server(int argc, char* argv[]); // Modo Servidor
  18.  
  19.  
  20.  private:    
  21.                        // VARIABLES GLOBALES
  22.      bool escuchando;
  23.  
  24.                          //     FUNCIONES
  25.      static unsigned __stdcall L2cap::Answer(void* a);
  26.     
  27. };
  28.  
  29.  
  30.  

L2cap.cpp

Código: Text
  1. #include <L2cap.h>
  2. #include <Socket.h>
  3. #include <process.h>
  4. #include <string>
  5. #include <sstream>
  6. #include <iostream>
  7. #include <cstdlib>
  8. #include <stdio.h>
  9.  
  10. using namespace std;
  11.  
  12.  
  13.  
  14. L2cap::L2cap ()  // Constructor
  15. {
  16.    escuchando = true;
  17. }
  18.  
  19.  
  20.  
  21. unsigned __stdcall L2cap::Answer(void* a)
  22. {
  23.   Socket* s = (Socket*) a;
  24.   int size;
  25.  
  26.   while (1) // escuchando
  27.   {
  28.     std::string r = s->ReceiveBytes();  
  29.     size = r.length();
  30.     if (size>0)
  31.     {  
  32.       if (escuchando);  // <- aqui obtengo el error. no la ve
  33.     }
  34.   }
  35.   delete s;
  36.   return 0;
  37. }
  38.  
  39.  
  40. void L2cap::Server(int argc, char* argv[]) // Modo Servidor
  41. {
  42.   SocketServer in(3000,5);
  43.  
  44.   while (escuchando)
  45.   {
  46.     Socket* s=in.Accept();
  47.     unsigned ret;
  48.     _beginthreadex(0,0,Answer,(void*) s,0,&ret);
  49.   }
  50. }
  51.  
  52.  
  53. void L2cap::Conecta()
  54. {
  55.     std::string cadena;
  56.  
  57.   try
  58.   {
  59.     SocketClient s("pc.", 3000); //Ya esta abierto, no tengo que hacerlo de nuevo.??
  60.     cadena = "1600010002050400010040000A06020001000607040043004000";
  61.     s.SendBytes(cadena);
  62.   }
  63.   catch (const char* s)
  64.   {
  65.     cerr << s << endl;
  66.   }
  67.   catch (std::string s)
  68.   {
  69.     cerr << s << endl;
  70.   }
  71.   catch (...)
  72.   {
  73.     cerr << "unhandled exception\n";
  74.   }
  75. }
  76.  
  77.  


programa principal: principal.cpp

Código: Text
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <L2cap.h>
  4.  
  5.  
  6. using namespace std;
  7.  
  8. int main()
  9. {
  10.     int opcion;
  11.     L2cap micapa;
  12.     
  13.     cout <<endl<<"                *-----------------------------------------*";
  14.     cout <<endl<<"                |  1.- Modo Servidor................. (1) |";
  15.     cout <<endl<<"                |  2.- Modo Cliente manda msg........ (2) |";
  16.     cout <<endl<<"                *-----------------------------------------*"<<endl<<endl;
  17.     cout <<endl<<"                  >  Elija una Opcion.......... ";
  18.     scanf("%d",&opcion);
  19.  
  20.   //Lee Menu y llama funciones
  21.   switch(opcion)
  22.     {
  23.          case 1:
  24.              {
  25.               micapa.Server(1,0);
  26.               break;
  27.              }
  28.          case 2:
  29.              {
  30.               micapa.Conecta();
  31.               break;
  32.              }  
  33.     }
  34.   return 0;
  35. }  
  36.  
  37.  


Y bueno, los archivos de la clase socket, son:

el socket.cpp

Código: Text
  1. #include <SOCKET.h>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6.  
  7. int Socket::nofSockets_= 0;
  8.  
  9.  
  10. void Socket::Start()
  11. {
  12.   if (!nofSockets_)
  13.   {
  14.     WSADATA info;
  15.     if (WSAStartup(MAKEWORD(2,0), &info))
  16.     {
  17.       throw "Could not start WSA";
  18.     }
  19.   }
  20.   ++nofSockets_;
  21. }
  22.  
  23.  
  24. void Socket::End()
  25. {
  26.   WSACleanup();
  27. }
  28.  
  29.  
  30. Socket::Socket() : s_(0)
  31. {
  32.   Start();
  33.   // UDP: use SOCK_DGRAM instead of SOCK_STREAM
  34.   s_ = socket(AF_INET,SOCK_STREAM,0);
  35.  
  36.   if (s_ == INVALID_SOCKET)
  37.   {
  38.     throw "INVALID_SOCKET";
  39.   }
  40.  
  41.   refCounter_ = new int(1);
  42. }
  43.  
  44.  
  45. Socket::Socket(SOCKET s) : s_(s)
  46. {
  47.   Start();
  48.   refCounter_ = new int(1);
  49. };
  50.  
  51.  
  52. Socket::~Socket()
  53. {
  54.   if (! --(*refCounter_))
  55.   {
  56.     Close();
  57.     delete refCounter_;
  58.   }
  59.  
  60.   --nofSockets_;
  61.   if (!nofSockets_) End();
  62. }
  63.  
  64.  
  65. Socket::Socket(const Socket& o)
  66. {
  67.   refCounter_=o.refCounter_;
  68.   (*refCounter_)++;
  69.   s_         =o.s_;
  70.  
  71.   nofSockets_++;
  72. }
  73.  
  74.  
  75. Socket& Socket::operator=(Socket& o)
  76. {
  77.   (*o.refCounter_)++;
  78.  
  79.   refCounter_=o.refCounter_;
  80.   s_         =o.s_;
  81.  
  82.   nofSockets_++;
  83.  
  84.   return *this;
  85. }
  86.  
  87.  
  88. void Socket::Close()
  89. {
  90.   closesocket(s_);
  91. }
  92.  
  93.  
  94. std::string Socket::ReceiveBytes()
  95. {
  96.   std::string ret;
  97.   char buf[1024];
  98.  
  99.   while (1) {
  100.     u_long arg = 0;
  101.     if (ioctlsocket(s_, FIONREAD, &arg) != 0)
  102.     {
  103.       break;
  104.     }
  105.  
  106.     if (arg == 0)
  107.     {
  108.       break;
  109.     }
  110.     
  111.     if (arg > 1024)
  112.     {
  113.             arg = 1024;
  114.     }
  115.  
  116.     int rv = recv (s_, buf, arg, 0);
  117.  
  118.     if (rv <= 0)
  119.     {
  120.            break;
  121.     }
  122.  
  123.     std::string t;
  124.  
  125.     t.assign (buf, rv);
  126.     ret += t;
  127.   }
  128.  
  129.   return ret;
  130. }
  131.  
  132.  
  133. std::string Socket::ReceiveLine()
  134. {
  135.   std::string ret;
  136.   while (1)
  137.   {
  138.     char r;
  139.  
  140.     switch(recv(s_, &r, 1, 0))
  141.     {
  142.       case 0: // not connected anymore;
  143.               // ... but last line sent
  144.               // might not end in \n,
  145.               // so return ret anyway.
  146.         return ret;
  147.  
  148.       case -1:
  149.         return "";
  150. //      if (errno == EAGAIN) {
  151. //        return ret;
  152. //      } else {
  153. //      // not connected anymore
  154. //      return "";
  155. //      }
  156.     }
  157.  
  158.     ret += r;
  159.     if (r == '\n')  return ret;
  160.   }
  161. }
  162.  
  163.  
  164. void Socket::SendLine(std::string s)
  165. {
  166.   s += '\n';
  167.   send(s_,s.c_str(),s.length(),0);
  168. }
  169.  
  170.  
  171. void Socket::SendBytes(const std::string& s)
  172. {
  173.   send(s_,s.c_str(),s.length(),0);
  174. }
  175.  
  176.  
  177. SocketServer::SocketServer(int port, int connections, TypeSocket type)
  178. {
  179.   sockaddr_in sa;
  180.  
  181.   memset(&sa, 0, sizeof(sa));
  182.  
  183.   sa.sin_family = PF_INET;            
  184.   sa.sin_port = htons(port);          
  185.   s_ = socket(AF_INET, SOCK_STREAM, 0);
  186.   if (s_ == INVALID_SOCKET)
  187.   {
  188.     throw "INVALID_SOCKET";
  189.   }
  190.  
  191.   if(type==NonBlockingSocket)
  192.   {
  193.     u_long arg = 1;
  194.     ioctlsocket(s_, FIONBIO, &arg);
  195.   }
  196.  
  197.   /* bind the socket to the internet address */
  198.   if (bind(s_, (sockaddr *)&sa, sizeof(sockaddr_in)) == SOCKET_ERROR)
  199.   {
  200.     closesocket(s_);
  201.     throw "INVALID_SOCKET";
  202.   }
  203.   
  204.   listen(s_, connections);                              
  205. }
  206.  
  207.  
  208. Socket* SocketServer::Accept()
  209. {
  210.   SOCKET new_sock = accept(s_, 0, 0);
  211.   if (new_sock == INVALID_SOCKET)
  212.   {
  213.     int rc = WSAGetLastError();
  214.     if(rc==WSAEWOULDBLOCK)
  215.     {
  216.       return 0; // non-blocking call, no request pending
  217.     }
  218.     else
  219.     {
  220.       throw "Invalid Socket";
  221.     }
  222.   }
  223.  
  224.   Socket* r = new Socket(new_sock);
  225.   return r;
  226. }
  227.  
  228.  
  229. SocketClient::SocketClient(const std::string& host, int port) : Socket()
  230. {
  231.   std::string error;
  232.  
  233.   hostent *he;
  234.   if ((he = gethostbyname(host.c_str())) == 0)
  235.   {
  236.     error = strerror(errno);
  237.     throw error;
  238.   }
  239.  
  240.   sockaddr_in addr;
  241.   addr.sin_family = AF_INET;
  242.   addr.sin_port = htons(port);
  243.   addr.sin_addr = *((in_addr *)he->h_addr);
  244.   memset(&(addr.sin_zero), 0, 8);
  245.  
  246.   if (::connect(s_, (sockaddr *) &addr, sizeof(sockaddr)))
  247.   {
  248.     error = strerror(WSAGetLastError());
  249.     throw error;
  250.   }
  251. }
  252.  
  253.  
  254. SocketSelect::SocketSelect(Socket const * const s1, Socket const * const s2, TypeSocket type)
  255. {
  256.   FD_ZERO(&fds_);
  257.   FD_SET(const_cast<Socket*>(s1)->s_,&fds_);
  258.   if(s2)
  259.   {
  260.     FD_SET(const_cast<Socket*>(s2)->s_,&fds_);
  261.   }    
  262.  
  263.   TIMEVAL tval;
  264.   tval.tv_sec  = 0;
  265.   tval.tv_usec = 1;
  266.  
  267.   TIMEVAL *ptval;
  268.   if(type==NonBlockingSocket)
  269.   {
  270.     ptval = &tval;
  271.   }
  272.   else
  273.   {
  274.     ptval = 0;
  275.   }
  276.  
  277.   if (select (0, &fds_, (fd_set*) 0, (fd_set*) 0, ptval) == SOCKET_ERROR)
  278.     throw "Error in select";
  279. }
  280.  
  281. bool SocketSelect::Readable(Socket const* const s)
  282. {
  283.   if (FD_ISSET(s->s_,&fds_)) return true;
  284.   return false;
  285. }
  286.  
  287.  


y el socket.h

Código: Text
  1. #ifndef SOCKET_H
  2. #define SOCKET_H
  3.  
  4. #include <WinSock2.h>
  5. #include <string>
  6.  
  7. enum TypeSocket {BlockingSocket, NonBlockingSocket};
  8.  
  9. class Socket {
  10.     public:
  11.     
  12.       virtual ~Socket();
  13.       Socket(const Socket&);
  14.       Socket& operator=(Socket&);
  15.     
  16.       std::string ReceiveLine();
  17.       std::string ReceiveBytes();
  18.     
  19.       void   Close();
  20.     
  21.       // The parameter of SendLine is not a const reference
  22.       // because SendLine modifes the std::string passed.
  23.       void   SendLine (std::string);
  24.     
  25.       // The parameter of SendBytes is a const reference
  26.       // because SendBytes does not modify the std::string passed
  27.       // (in contrast to SendLine).
  28.       void   SendBytes(const std::string&);
  29.     
  30.     protected:
  31.       friend class SocketServer;
  32.       friend class SocketSelect;
  33.     
  34.       Socket(SOCKET s);
  35.       Socket();
  36.     
  37.     
  38.       SOCKET s_;
  39.     
  40.       int* refCounter_;
  41.     
  42.     private:
  43.       static void Start();
  44.       static void End();
  45.       static int  nofSockets_;
  46.  
  47. };
  48.  
  49.  
  50. class SocketClient : public Socket
  51. {
  52.     public:
  53.       SocketClient(const std::string& host, int port);
  54. };
  55.  
  56.  
  57.  
  58. class SocketServer : public Socket
  59. {
  60.     public:
  61.       SocketServer(int port, int connections, TypeSocket type=BlockingSocket);
  62.     
  63.       Socket* Accept();
  64. };
  65.  
  66.  
  67. class SocketSelect {
  68.   public:
  69.     SocketSelect(Socket const * const s1, Socket const * const s2=NULL, TypeSocket type=BlockingSocket);
  70.  
  71.     bool Readable(Socket const * const s);
  72.  
  73.   private:
  74.     fd_set fds_;
  75. };
  76.  
  77. #endif
  78.  
  79.  


Con eso ya se puede compilar el programa creando un proyecto con esos archivos, y el error obtenido es el que no es un uso válido en un miembro estático.

A ver si pudiesemos encontrar la solución, muchisimas gracias.

pd: La clase socket, fue realizada por René Nyffenegger.

42
C/C++ / Re: Problema Con _beginthreadex En Una Clase
« en: Miércoles 7 de Noviembre de 2007, 21:38 »
Muchas gracias de nuevo. La comunicación por sockets la requiero porque me es necesario para simular el comportamiento entre dos instancias de mi programa, que se estén ejecutando, ya sea en la misma máquina o en máquinas distintas.

No he entendido muy bien la solución de crearme otro miembro en la clase l2cap, ¿a que se refiere? :(

De todas formas muchas gracias por tus respuestas Eternal Idol.

43
C/C++ / Re: Problema Con _beginthreadex En Una Clase
« en: Miércoles 7 de Noviembre de 2007, 08:48 »
¿Que significa declarar esa función como static Eternal Idol? Es que soy totalmente novato en la programación y me pierdo. :(

El código que yo tengo en mi programa, y que da problemas, es el de abajo del primer post.

Las declaraciones las tengo tal y como están ahí, pero obtengo el error de tipos ese que he resaltado en negrita.

¿Puede ser que beginthreadex no pueda usarse dentro de una clase?

Si le quito el que esté dentro de mi clase, es decir, si la función Answer no la defino como L2cap::Answer, y en los parámetros elimino también el L2cap:: (en beginthreadex, para Answer), el código funciona. Pero si no incluyese referencia a ningún objeto de mi clase L2cap. En cuanto hago referencia a una variable por ejemplo, obtengo el error de que no está definida.

Es que creo que no me había explicado bien del todo.

Un saludo y muchísimas gracias de nuevo.

44
C/C++ / Re: Problema Con _beginthreadex En Una Clase
« en: Martes 6 de Noviembre de 2007, 15:27 »
Hola.

Si, efectivamente. Dentro de mi clase, uso la clase socket para establecer una conexion con otra clase igual que la mia.

La declaración de beginthreadex que tengo puesta en mi código es esa misma, y obtengo el error siguiente:

In member function 'void L2cap::Server (int,char**)'
argument of type 'unsigned int (L2cap:: )(void*) does not match 'unsigned int (*)(void*)')
Buil error (L2cap.o) Error 1.


Parece que al estar dentro de mi clase L2cap, obtiene un error de parámetros o algo. Ahi es donde tengo el problema.

45
C/C++ / Problema Con _beginthreadex En Una Clase
« en: Martes 6 de Noviembre de 2007, 08:05 »
Hola.

Es mi primer mensaje en el foro. Aprovecho para saludar y daros a todos las gracias por vuestra ayuda.

Soy un programador mas o menos novato, y no tengo mucha o ninguna idea de muchas, cosas, y bueno.

Vereis. Para la implementación del programa que estoy haciendo, he tenido que usar comunicación por sockets, para que se comuniquen dos entidades de mi programa.

Y para ello he usado una clase socket implementada, que contaba con ejemplos de servidor y de cliente.

El problema está en que estoy usando dicha clase socket, en una clase mia que me he creado.

El código de la clase socket, para un servidor, tal y como estaba definido por el autor de la clase es el siguiente (no es el que yo tengo en mi programa, que lo he puesto mas abajo):


Código: Text
  1. unsigned __stdcall Answer(void* a) {
  2.   Socket* s = (Socket*) a;
  3.  
  4.   while (1) {
  5.     std::string r = s->ReceiveLine();
  6.     if (r.empty()) break;
  7.     s->SendLine(r);
  8.   }
  9.  
  10.   delete s;
  11.  
  12.   return 0;
  13. }
  14.  
  15.  
  16. int main(int argc, char* argv[]) {
  17.   SocketServer in(2000,5);
  18.  
  19.   while (1) {
  20.     Socket* s=in.Accept();
  21.  
  22.     unsigned ret;
  23.     _beginthreadex(0,0,Answer,(void*) s,0,&ret);
  24.   }
  25.   
  26.   return 0;
  27. }
  28.  
  29.  




En mi programa, mi problema está en que yo estoy haciendo uso de dicha clase socket, y de actuar como servidor, dentro de una clase que me he creado. Y el problema que tengo es que, tras recibir datos por el socket, yo quiero comprobar si son un tipo de datos u otros, y uso variables globales pertenecientes a mi clase.


Para trabajar en mi clase tendre que declarar la función main como Nombremiclase::Server(int arg...).

Y para ver las variables globales desde la stdcall, supongo que tendré que ponerla en mi clase también...

No se, llevo varios dias intentandolo y estoy hundido, no hay manera. A ver si alguien supiese.



Os dejo el codigo que tengo implementado en mi clase, y el error que obtengo, que es :

In member function 'void L2cap::Server (int,char**)'
argument of type 'unsigned int (L2cap:: )(void*) does not match 'unsigned int (*)(void*)')
Buil error (L2cap.o) Error 1.


Código: Text
  1.  
  2. unsigned __stdcall L2cap::Answer(void* a)
  3. {
  4.   L2capChannel canal;
  5.   Socket* s = (Socket*) a;
  6.     unsigned int longitud, leidos, tipo, pos, NumBytes,opt;
  7.       unsigned int* datain = NULL;
  8.     int size;
  9.  
  10.  
  11.  
  12.   while (1) // escuchando
  13.   {
  14.     std::string r = s->ReceiveBytes();
  15.     
  16.     size = r.length();
  17.     L2cap::string_to_bytearray(r,datain,size);
  18.     
  19.  
  20.     Write(datain,size);
  21.  
  22.     longitud = size-4; // se trata del campo length, mientras q size es toda
  23.  
  24.  
  25.    tipo = Leertipotrama (datain);
  26.  
  27.     
  28.     if (r =="exit")
  29.     {
  30. //          escuchando = false;
  31. //          cout<<"Escuchando se ha puesto a false"<<endl;
  32.     }
  33.     else if ((r.length())>0)
  34.     {
  35.        cout <<"Recibida una string de longitud "<<r.length()<<endl<<"y contenido: "<<r<<endl<<endl;                
  36.        canal.EntradaDatos(r);
  37.     }
  38.  
  39. //    s->SendBytes(r);
  40.   }
  41.   delete s;
  42.  
  43.   return 0;
  44. }
  45.  
  46.  
  47.  
  48. void L2cap::Server(int argc, char* argv[]) // Modo Servidor
  49. {
  50.   SocketServer in(3000,5);
  51.  
  52.   while (escuchando)
  53.   {
  54.     Socket* s=in.Accept();
  55.  
  56.     unsigned ret;
  57.     _beginthreadex(0,0,L2cap::Answer,(void*) s,0,&ret);
  58.   }
  59. }
  60.  
  61.  


Ojalá podais ayudarme, muchísimas gracias de antemano.

Un saludo.

Páginas: 1 [2]