Thread View: es.comp.os.linux.programacion
6 messages
6 total messages
Started by Marc Franquesa
Tue, 27 Dec 2005 15:08
Usar un socket UDP con origen y destino
Author: Marc Franquesa
Date: Tue, 27 Dec 2005 15:08
Date: Tue, 27 Dec 2005 15:08
75 lines
3655 bytes
3655 bytes
Para una de esas cosas 'raras' de practicas debo implementar algo parecido a un protocolo orientado a conexión sobre UDP. Para eso he creado mi propio protocolo encima de UDP, però mi problema viene con la gestión de los sockets: Esta es la situación: 1) Un cliente que se conecta a 127.0.0.1:10000 Para tal conexión hago un socket() y luego un connect(), que aunque UDP no sea orientado a conexión hace que sólo envie y reciba del host al que me conecto. 2) Un servidor que 'escucha' en el puerto 127.0.0.1:10000 Para eso sólo hago un bind() al puerto 10000 y luego reads hasta que reciba la petición de conexión en mi capa (por encima de UDP). Dado que UDP no és orientado no necesito (ni puedo, ni debo) hacer ni un listen() ni ningún accept(). El socket() y bind() funcionan, ya que mi capa en el servidor al que he hecho bind() recibe los paquetes correctamente. Mi problema: Una vez mi capa ha leído y accpetado como correcto lo que he recibido en el socket del servidor, debo poder comunicarme con ese cliente. El problema aquí és que el socket del servidor no está 'conectado' (es UDP), por lo que cada vez que envie debo especificar el destino con sendto(). Aquí no hay demasiado problema, pero como hago para 'recibir' _SÓLO_DE_ESE_CLIENTE ? recvfrom no sirve para eso. Además cliente y servidor comparten el código de mi capa, con lo que debo usar la misma llamada (write/sendto) en ambos (no es demasiado problema). Una opción que se me ha ocurrido es conectar también el socket del servidor. De esta forma hago un connect() al cliente que me ha solicitado la conexión y me olvido de direcciones usando sólo (read/write). El problema és que debo mantener la dirección local de origen, ya que és la que usa el cliente para comunicar-se conmigo, però me da un 'Address already in use'. Lo que no entiendo, ya que creía que esto sólo passava al haber hecho un listen(). ¿Cómo se hace para escoger dirección de origen y de destino? ¿No debería ser con un bind() y un connect() ? Espero haber-me explicado que alguien más lumbreras que yo me diga dónde está mi error (que probablemente es mas de enfoque que de implementación) Muchas gracias. Por cierto: ¿Alguien sabe si hay alguna mètodo para definir un protocolo nuevo al Ethereal y facilitarme aún más la tarea? Ya puestos y que es Navidad (Feliz Navidad y año nuevo)
Re: Usar un socket UDP con origen y destino
Author: iarenaza
Date: Tue, 27 Dec 2005 17:46
Date: Tue, 27 Dec 2005 17:46
30 lines
2288 bytes
2288 bytes
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
>>>>> "Marc" == Marc Franquesa <mark@l3jane.net> writes:
Marc> problema, pero como hago para 'recibir'
Marc> _SÓLO_DE_ESE_CLIENTE ? recvfrom no sirve para eso.
No s� a que te refieres con recibir lo de ese cliente. Como es UDP, y
no existen conexiones l�gicas, cada env�o UDP es 100% independiente de
los anteriores. Es como si fuera una nueva petici�n. Es el c�digo de
tu servidor quien debe reconocer que tiene una transacci�n en marcha
con ese cliente desde antes y tratarlo como tal.
Es decir, debes incorporar toda la l�gica de gesti�n de conexiones
(inicio, mantenimiento, cierre) en tu servidor.
Saludos. I�aki.
- --
Get PGP/GPG Keys at http://www.escomposlinux.org/iarenaza/pgpkey.php
I use free software / Yo uso software libre
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/>
iD8DBQFDsX3iZXLnGT1HLgcRAk3xAJ44KTfKq3TNXAsnUfSv5szFSmT2BwCffTGe
IgaJlEFX+WtM/u+GUOmvDjc=
=6pu/
-----END PGP SIGNATURE-----
Re: Usar un socket UDP con origen y destino
Author: Oscar Garcia
Date: Tue, 27 Dec 2005 18:45
Date: Tue, 27 Dec 2005 18:45
114 lines
5847 bytes
5847 bytes
El Tue, 27 Dec 2005 16:08:42 +0100, Marc Franquesa <mark@l3jane.net> escribi�: >Para una de esas cosas 'raras' de practicas debo implementar algo >parecido a un protocolo orientado a conexi�n sobre UDP. Es reinventar la rueda, pero veamos como te las apa�as :) >Para eso he creado mi propio protocolo encima de UDP, per� mi problema >viene con la gesti�n de los sockets: >Esta es la situaci�n: Veamosla. >1) Un cliente que se conecta a 127.0.0.1:10000 >Para tal conexi�n hago un socket() y luego un connect(), que aunque UDP >no sea orientado a conexi�n hace que s�lo envie y reciba del host al que >me conecto. No hombre. Con socket creas las estructuras asociadas al socket que est�s creando. Para conectarte a una m�quina remota no necesitas un "connect", ni siquiera un "bind" (que ser�a necesario en caso de que no quieras que el SO elija por t� ip y puerto local). Con UDP como cliente basta con rellenar los campos de la estructura socket y en sendto y recvfrom dar como par�metro una estructura que ser� rellenada con los datos del host remoto que nos transmite tanto por nosotros mismos para indicar al host con el que queremos comunicarnos. >2) Un servidor que 'escucha' en el puerto 127.0.0.1:10000 >Para eso s�lo hago un bind() al puerto 10000 y luego reads hasta que >reciba la petici�n de conexi�n en mi capa (por encima de UDP). >Dado que UDP no �s orientado no necesito (ni puedo, ni debo) hacer ni un >listen() ni ning�n accept(). >El socket() y bind() funcionan, ya que mi capa en el servidor al que he >hecho bind() recibe los paquetes correctamente. Pero deber�as implementar una capa en tu protocolo que abstraiga los m�todos bind, connect, etc usando paquetes UDP. Lo normal es enviar un paquete UDP solicitando la conexi�n y que tu aplicaci�n la permita o la rechace no sin antes pasarle mediante un callback a la aplicaci�n interesada que dicha conexi�n se ha producido. >Mi problema: > >Una vez mi capa ha le�do y accpetado como correcto lo que he recibido en >el socket del servidor, debo poder comunicarme con ese cliente. >El problema aqu� �s que el socket del servidor no est� 'conectado' (es >UDP), por lo que cada vez que envie debo especificar el destino con >sendto(). Aqu� no hay demasiado problema, pero como hago para 'recibir' >_S�LO_DE_ESE_CLIENTE ? recvfrom no sirve para eso. Debes crearte una estructura a nivel de tu aplicaci�n que guarde todos los valores de ambos extremos una vez que se haya terminado el proceso de establecimiento de conexi�n. Esto implica que todo lo tendr�s previamente almacenado en memoria (los sockaddr_in del otro extremo, por ejemplo). >Adem�s cliente y servidor comparten el c�digo de mi capa, con lo que >debo usar la misma llamada (write/sendto) en ambos (no es demasiado >problema). �Cual es la duda? >Una opci�n que se me ha ocurrido es conectar tambi�n el socket del >servidor. De esta forma hago un connect() al cliente que me ha >solicitado la conexi�n y me olvido de direcciones usando s�lo >(read/write). Entonces estar�as usando TCP y no UDP. >El problema �s que debo mantener la direcci�n local de origen, ya que �s >la que usa el cliente para comunicar-se conmigo, per� me da un 'Address >already in use'. Lo que no entiendo, ya que cre�a que esto s�lo passava >al haber hecho un listen(). A ver. Eso es posiblemente porque has hecho un bind y has ocupado un puerto local y/o ip local para enviar datos, de modo que no se puede usar ese mismo puerto para enviar m�s datos. >�C�mo se hace para escoger direcci�n de origen y de destino? �No deber�a >ser con un bind() y un connect() ? En UDP se especifica en el sendto directamente. >Espero haber-me explicado que alguien m�s lumbreras que yo me diga d�nde >est� mi error (que probablemente es mas de enfoque que de >implementaci�n) Sinceramente no me ha quedado muy claro lo que deseas conseguir. En un principio pens� que deseas implementar (quiz� para un trabajo de la universidad) una capa de transporte de datos orientado a conexi�n haciendo uso de una capa inferior no orientada a conexi�n. Luego m�s bien parece que lo que deseas es establecer un protocolo abstracto (que no entiendo demasiado bien) en el que deseas simplemente comunicar dos aplicaciones usando unas funciones sencillas y que se almacenen autom�ticamente los datos locales y remotos. Si te explicas un poco mejor la verdad que lo agradeceremos. >>Ya puestos y que es Navidad (Feliz Navidad y a�o nuevo) FELIZ NAVIDAD, A�O 2006 Y A�OS VENIDEROS. Un saludo. -- �scar Javier Garc�a Baudet LinaresDigital http://redstar.linaresdigital.com/
Re: Usar un socket UDP con origen y destino
Author: Count Zero
Date: Wed, 28 Dec 2005 11:07
Date: Wed, 28 Dec 2005 11:07
125 lines
6587 bytes
6587 bytes
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 En/na Oscar Garcia ha escrit: > No hombre. Con socket creas las estructuras asociadas al socket que > est�s creando. Para conectarte a una m�quina remota no necesitas un > "connect", ni siquiera un "bind" (que ser�a necesario en caso de que > no quieras que el SO elija por t� ip y puerto local). Te recurdo que me intento es 'emular' un protocolo orientado a conexi�n. A�n as� de tu comentario deduzco que con un bind() y luego un connect() puedo elegir direcci�n y puerto local y remotos tanto en UDP como en TCP. Se puede as�? > Con UDP como cliente basta con rellenar los campos de la estructura > socket y en sendto y recvfrom dar como par�metro una estructura que > ser� rellenada con los datos del host remoto que nos transmite tanto > por nosotros mismos para indicar al host con el que queremos > comunicarnos. Si ya lo s�, pero uso el connect() precisamente por qu� me garantiza que la capa UDP s�lo leear� paquetes enviadados des del extremo al que me he 'conectado' aunque UDP no sea orientado a conexi�n. Eso me ahorra tener que usar recvfrom() o sendto() por ejemplo. > Pero deber�as implementar una capa en tu protocolo que abstraiga los > m�todos bind, connect, etc usando paquetes UDP. Y as� lo he echo. > Lo normal es enviar un paquete UDP solicitando la conexi�n y que tu > aplicaci�n la permita o la rechace no sin antes pasarle mediante un > callback a la aplicaci�n interesada que dicha conexi�n se ha > producido. (Supongo que con 'callback' indicas algo tipo el SYN+ACK del TCP, que es similar a lo que yo hago.) Precisamente en este punto es donde tengo problemas: Una vez el servidor ha acceptado (y notificado al cliente) la 'conexi�n', el cliente ya puede transmitir y recibir sin problemas, ya que el socket ya est� "conectado" al servidor. Pero el servidor en ese momento s�lo dispone de un socket UDP associado localmente mediante bind() que, aqu� mi problema, RECIBE DE QUALQUIER CLIENTE. Por lo tanto necesito un m�todo para distinguir diversos clientes (flujos), y como muy bien apunta I�aki, UDP no tiene concepto de flujo por lo que me las debo apa�ar yo. Mi idea era intentar emular el accept() de TCP m�s o menos as�: - - Una vez acceptada la conexi�n el servidor creo un nuevo socket - - Con bind() lo associo al puerto local donde doy servicio (que �s por d�nde el cliente me enviar� datagramas). - - Con connect() lo associo al cliente que ha pedido la conexi�n. Aunque UDP no �s orientado, eso me garantiza que S�LO RECIBIR� DATAGRAMAS DE ESE CLIENTE (man dixit) > Debes crearte una estructura a nivel de tu aplicaci�n que guarde todos > los valores de ambos extremos una vez que se haya terminado el proceso > de establecimiento de conexi�n. Esto implica que todo lo tendr�s > previamente almacenado en memoria (los sockaddr_in del otro extremo, > por ejemplo). Ya tengo esa estructura, s�lo que hasta el momento intentaba evitar tener que almacenar esa informaci�n, pero veo que ya va siendo hora de que toque de pies al suelo y lo haga. > Entonces estar�as usando TCP y no UDP. No, la llamada socket() especifica el tipo de protocolo via SOCK_DGRAM o SOCK_STREAM, connect() y bind() no hacen nada al respecto. (Mira las p�ginas de man) > A ver. Eso es posiblemente porque has hecho un bind y has ocupado un > puerto local y/o ip local para enviar datos, de modo que no se puede > usar ese mismo puerto para enviar m�s datos. Ten�a entendido (quiz� me equivoco) que el sistema identifica una conexi�n/socket por la tupla direcci�n-local:puerto-local/direcci�n-remota:puerto-remoto, por lo que cre�a que podr�a hacer el bind() a�n y ya tener un socket en ese puerto, pero se queja con el error "Address already in use", por lo que debo destimar este enfoque. > En UDP se especifica en el sendto directamente. En el sendto() no hay problema: YO digo al sistema D�NDE enviar. El problema �s con recvfrom(), el SISTEMA me dice de D�NDE he recibido, cuando yo lo que quiero �s poder indicar-le de que direcci�n deseo recibir. Evidentemente puedo recibir y luego "separar" el flujo seg�n la direcci�n remota, pero esto complica mucho el c�digo. Tambi�n havia pensado en usar MSG_PEEK, para dejar el datagrama en la cola caso de no interessarme, per� no lo veo muy fiable para m�s intereses. > Sinceramente no me ha quedado muy claro lo que deseas conseguir. Lo s� > En un principio pens� que deseas implementar (quiz� para un trabajo de > la universidad) una capa de transporte de datos orientado a conexi�n > haciendo uso de una capa inferior no orientada a conexi�n. Exactamente esto! > Si te explicas un poco mejor la verdad que lo agradeceremos. Espero haverlo hecho, a�n as� los comentarios me han hecho ver lo que tem�a: iba por mal camino. Pero pens� que quiz� alguien ver�a una forma m�s simple de hacerlo. Muchas gracias. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFDsnHh4CVRFTc6wP8RAgmVAJ9/GXdFfy/dAHCcIfqO/555srOsIwCfRPid 1SY3+yUAb/tZ8ult9bv2ri8= =XLNT -----END PGP SIGNATURE-----
Re: Usar un socket UDP con origen y destino
Author: Count Zero
Date: Wed, 28 Dec 2005 11:11
Date: Wed, 28 Dec 2005 11:11
42 lines
2612 bytes
2612 bytes
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 En/na (I�aki Arenaza) ha escrit: > No s� a que te refieres con recibir lo de ese cliente. Como es UDP, y > no existen conexiones l�gicas, cada env�o UDP es 100% independiente de > los anteriores. Es como si fuera una nueva petici�n. Es el c�digo de El servidor tiene un socket associado localmente con bind(), eso hace que pueda recibir de qualquier direcci�n remota. En un momento dado me interessa limitarme a procesar los datagramas que provienen s�lo de una direcci�n (el cliente). (De hecho aunque UDP no sea orientado, si hago un connect, la capa de sockets s�lo recibe de la direcci�n a la que he hecho el connect) > tu servidor quien debe reconocer que tiene una transacci�n en marcha > con ese cliente desde antes y tratarlo como tal. Es lo que me tem�a, pero pens� que quiz� alguien tendr�a alguna soluci�n /workarround/hack. > Es decir, debes incorporar toda la l�gica de gesti�n de conexiones > (inicio, mantenimiento, cierre) en tu servidor. (Maldita sea!) > Saludos. I�aki. Saludos y muchas gracias. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFDsnL84CVRFTc6wP8RAsgyAJ9zffM9j5CeU7IJCi7rtPzvNeGW4QCgzx0I T2yeDr0x5g4OM0Ib1W87TfM= =zcA5 -----END PGP SIGNATURE-----
Re: Usar un socket UDP con origen y destino
Author: Oscar Garcia
Date: Wed, 28 Dec 2005 12:10
Date: Wed, 28 Dec 2005 12:10
124 lines
6890 bytes
6890 bytes
El Wed, 28 Dec 2005 12:07:13 +0100, Count Zero <mark@l3jane.net> escribi�: >> No hombre. Con socket creas las estructuras asociadas al socket que >> est�s creando. Para conectarte a una m�quina remota no necesitas un >> "connect", ni siquiera un "bind" (que ser�a necesario en caso de que >> no quieras que el SO elija por t� ip y puerto local). > >Te recurdo que me intento es 'emular' un protocolo orientado a conexi�n. >A�n as� de tu comentario deduzco que con un bind() y luego un connect() >puedo elegir direcci�n y puerto local y remotos tanto en UDP como en >TCP. Se puede as�? S�, pero piensa as� s�lo en el extremo cliente si lo deseas, en el lado del servidor no debes pensar as�. Cuando un cliente va a transmitir datos a un servidor, �ste se dedicar� a enviarlos a un puerto destino usando siempre el mismo puerto fuente. Las parejas puerto/ip fuente y puerto/ip destino son las que definen una conexi�n �nica. En tu implementaci�n debes pensar en la parte del servidor debes crear un socket que escuche en un puerto local, pero que acepte cualquier puerto remoto ya que en caso contrario no podr�s aceptar conexiones "nuevas". Como tienes el socket UDP escuchando en un puerto local aceptando cualquier puerto remoto no te dejar� posteriormente hacer un connect a un socket nuevo sin cerrar previamente el anterior. En este caso debes implementar en tu software de servidor un send y recv que ponga autom�ticamente los datos remotos y locales en cada paquete que envies con recvfrom y sendto. Hay que tener especial cuidado al aceptar paquetes de un mismo host con puerto origen distinto a una conexi�n establecida (tu software debe preveer eso y considerarlo como un intento de conexi�n nueva). >> Lo normal es enviar un paquete UDP solicitando la conexi�n y que tu >> aplicaci�n la permita o la rechace no sin antes pasarle mediante un >> callback a la aplicaci�n interesada que dicha conexi�n se ha >> producido. > >(Supongo que con 'callback' indicas algo tipo el SYN+ACK del TCP, que es >similar a lo que yo hago.) > >Precisamente en este punto es donde tengo problemas: > >Una vez el servidor ha acceptado (y notificado al cliente) la >'conexi�n', el cliente ya puede transmitir y recibir sin problemas, ya >que el socket ya est� "conectado" al servidor. El cliente s�, pero como acabo de decirte, el servidor NO. >Pero el servidor en ese momento s�lo dispone de un socket UDP associado >localmente mediante bind() que, aqu� mi problema, RECIBE DE QUALQUIER >CLIENTE. Por lo tanto necesito un m�todo para distinguir diversos >clientes (flujos), y como muy bien apunta I�aki, UDP no tiene concepto >de flujo por lo que me las debo apa�ar yo. > >Mi idea era intentar emular el accept() de TCP m�s o menos as�: Quiz� no entiendas bien como trabaja la capa de red en TCP y por eso no llegas a entender la complejidad de lo que deseas hacer. >- - Una vez acceptada la conexi�n el servidor creo un nuevo socket >- - Con bind() lo associo al puerto local donde doy servicio (que �s por >d�nde el cliente me enviar� datagramas). >- - Con connect() lo associo al cliente que ha pedido la conexi�n. Aunque >UDP no �s orientado, eso me garantiza que S�LO RECIBIR� DATAGRAMAS DE >ESE CLIENTE (man dixit) Por lo pronto espero que entiendas porqu� te dice "address already in use". No puedes hacer ni un bind ni un connect a un puerto local ya usado por un servidor ya que se supone que espera datos de "cualquier" puerto remoto (para poder aceptar conexiones nuevas de cualquier equipo remoto). Eso deja en uso dicho puerto local y no podr�s fijar con bind ning�n otro socket a dicho puerto. >> Debes crearte una estructura a nivel de tu aplicaci�n que guarde todos >> los valores de ambos extremos una vez que se haya terminado el proceso >> de establecimiento de conexi�n. Esto implica que todo lo tendr�s >> previamente almacenado en memoria (los sockaddr_in del otro extremo, >> por ejemplo). > >Ya tengo esa estructura, s�lo que hasta el momento intentaba evitar >tener que almacenar esa informaci�n, pero veo que ya va siendo hora de >que toque de pies al suelo y lo haga. Espero que ahora entiendas que es NECESARIO usarla. >> Entonces estar�as usando TCP y no UDP. > >No, la llamada socket() especifica el tipo de protocolo via SOCK_DGRAM o >SOCK_STREAM, connect() y bind() no hacen nada al respecto. (Mira las >p�ginas de man) Hasta ahora hab�a usado bind en un UDP, pero no connect. >> A ver. Eso es posiblemente porque has hecho un bind y has ocupado un >> puerto local y/o ip local para enviar datos, de modo que no se puede >> usar ese mismo puerto para enviar m�s datos. > >Ten�a entendido (quiz� me equivoco) que el sistema identifica una >conexi�n/socket por la tupla >direcci�n-local:puerto-local/direcci�n-remota:puerto-remoto, por lo que >cre�a que podr�a hacer el bind() a�n y ya tener un socket en ese puerto, >pero se queja con el error "Address already in use", por lo que debo >destimar este enfoque. Exacto, y esa es la idea, pero al crear el socket escuchando en un puerto.. est�s "fijando" un socket a un puerto local y cualquier ip local y puerto/ip remoto, de modo que cualquier intento de fijar de nuevo otro socket a dicho puerto local es infructuoso. Espero que hayas entendido la complejidad real del servidor que intentas crear no puede reducirse usando connect y bind como pensabas. Un saludo. -- �scar Javier Garc�a Baudet LinaresDigital http://redstar.linaresdigital.com/
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads