🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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
#1264
Author: Marc Franquesa
Date: Tue, 27 Dec 2005 15:08
75 lines
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
#1265
Author: iarenaza
Date: Tue, 27 Dec 2005 17:46
30 lines
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
#1266
Author: Oscar Garcia
Date: Tue, 27 Dec 2005 18:45
114 lines
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
#1267
Author: Count Zero
Date: Wed, 28 Dec 2005 11:07
125 lines
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
#1268
Author: Count Zero
Date: Wed, 28 Dec 2005 11:11
42 lines
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
#1269
Author: Oscar Garcia
Date: Wed, 28 Dec 2005 12:10
124 lines
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