networking - UDP API en Rust
(2)
1) API para enviar aquí devuelve Result<usize>
. Porqué es eso ? En mi cabeza, un envío UDP es todo o nada. El valor de retorno parece sugerir que el envío puede tener éxito, pero puede que no se escriban datos completos, lo que me hace codificar de la siguiente manera:
let mut bytes_written = 0;
while bytes_written < data.len() {
bytes_written += match udp_socket.send_to(&data[bytes_written..]) {
Ok(bytes_tx) => bytes_tx,
Err(_) => break,
}
}
Recientemente, alguien me dijo que esto es completamente innecesario. Pero no entiendo Si eso fuera cierto, ¿por qué el Result<()>
no es Result<()>
, que también es lo que esperaba?
2) Para lecturas, aunque entiendo. Podría darle un buffer de tamaño 100 bytes pero el datagrama podría tener solo 50 bytes de longitud. Entonces, esencialmente, debería utilizar solo read_buf[..size_read]
. Aquí mi pregunta es ¿qué ocurre si el tamaño del buffer es 100 pero el tamaño del datagrama es de 150 bytes? ¿ recv_from
completará solo 100 bytes y devolverá Ok(100, some_peer_addr)
? Si vuelvo a leer ¿completará el datagrama restante? ¿Qué pasa si otro datagrama de 50 bytes llegó antes de mi segunda lectura? ¿Obtendré solo los 50 bytes restantes la segunda vez y 50 bytes de datagrama nuevo la 3ª vez o completaré 100 bytes la 2ª vez que también contiene el nuevo datagrama? ¿O será un error y perderé el primer datagrama en mi lectura inicial y nunca podré recuperarlo?
La respuesta a ambas preguntas radica en la documentación de las funciones de los zócalos BSD respectivos, sendto()
y recvfrom()
. Si usa algún sistema * nix (OS X o Linux, por ejemplo), puede usar man sendto
y man recvfrom
para encontrarlo.
1) la página man de sendto()
es bastante vaga en esto; La página de la API de Windows dice explícitamente que es posible que el valor de retorno sea menor que el argumento len
. Ver también esta pregunta. Parece que este momento particular está poco documentado. Creo que probablemente sea seguro suponer que el valor de retorno siempre será igual a len
o al código de error. Pueden surgir problemas si la longitud de los datos enviados a través de sendto()
excede el tamaño del búfer interno dentro del kernel del sistema operativo, pero parece que al menos Windows devolverá un error en este caso.
2) La página man de recvfrom()
declara inequívocamente que la parte de un datagrama que no cabe en el buffer será descartada:
La función recvfrom () devolverá la longitud del mensaje escrito en el búfer al que apunta el argumento del búfer. Para los sockets basados en mensajes, como SOCK_RAW, SOCK_DGRAM y SOCK_SEQPACKET, todo el mensaje se leerá en una sola operación. Si un mensaje es demasiado largo para caber en el búfer proporcionado, y MSG_PEEK no se establece en el argumento de indicadores, los bytes en exceso se descartarán.
Así que sí, recv_from()
llenará exactamente 100 bytes, el resto se descartará, y las llamadas posteriores a recv_from()
devolverán nuevos datagramas.
Si cavas hacia abajo , simplemente ajusta la función C enviar a . Esta función devuelve el número de bytes enviados, por lo que Rust simplemente lo pasa (mientras maneja el caso -1 y convierte errno en errores reales).