UDP Client does not EVER receive packets back!

I am sending packets back to the client, from the server but he never gets them. He is bind on port 8000 and server is bind on 8080. I use Tokio, and I send the packet back with:

  thread_socket.send_to(&*missing_chunks, ADDRESS_CLIENT).await;

I init the socket on the server side with

let socket_out = UdpSocket::bind(ADDRESS_OUT).await.unwrap();
let arc_out = Arc::new(socket_out);
let thread_socket = arc_out.clone();

(ideally I wanted to use let arc= = Arc::new(socket); let thread_socket = arc.clone(); but I get the error with generator: -- variable moved due to use in generator and value borrowed here after move and after 3h of pointless coding I decided to rage quit with this fix trying many things I have still no idea how to fix it so I thought " Okay I might just create another port then..." )


on the client side I wait for the packets with

let len:usize = socket.recv(&mut buffer).await.unwrap();

I init the socket on client side with

let remote_addr: SocketAddr = env::args()
        .nth(1)
        .unwrap_or_else(|| "127.0.0.1:8080".into()) // cargo run --example udp-client -- 127.0.0.1:8080
        .parse()?;

    // We use port 0 to let the operating system allocate an available port for us.
    let local_addr: SocketAddr = if remote_addr.is_ipv4() {
       "127.0.0.1:8000"// "0.0.0.0:0" //
    } else {
        "[::]:0"
    }
    .parse()?;
let socket = UdpSocket::bind(local_addr).await?;
socket.connect(&remote_addr).await?;
  • This is where I have the difficulties on the server side: althought it says that the data is sent.
  • This is where I am awaiting the server packets on the client side (and they never arrive)

I really want to scream "HELP HELP please please" but I will try to preserve some dignity after 2 days of worthless coding :< Any help really strongly appreciated, willing to sell my soul for it.

If you're unsure whether the basic communication works at all, it helps to start with a really bare-bones implementation and expand from that. Here is a combined client/server program which sends a UDP packet with an increasing sequence number every second (in server mode, srv as the first argument), and receives those packets and prints them out (in client mode, no arguments):

// tokio = { version = "1", features = ["full"] }

use std::env;
use std::error::Error;
use std::net::SocketAddr;
use std::process;
use std::time::Duration;

use tokio::net::UdpSocket;
use tokio::time::sleep;

#[derive(Clone, Debug)]
enum Mode {
    Client,
    Server,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let mode = match env::args().nth(1) {
        None => Mode::Client,
        Some(ref m) if m == "srv" => Mode::Server,
        _ => {
            eprintln!("Usage: udpsc [srv]");
            process::exit(1);
        },
    };
    match mode {
        Mode::Client => do_client().await,
        Mode::Server => do_server().await,
    }
}

async fn do_client() -> Result<(), Box<dyn Error>> {
    let cli = UdpSocket::bind("0.0.0.0:8000").await?;
    cli.connect("127.0.0.1:8080").await?;
    let mut buf = [0u8; 16];
    loop {
        match cli.recv(&mut buf).await {
            Ok(_) => if let Ok(s) = std::str::from_utf8(&buf[..]) {
                println!("{}", s);
            },
            Err(e) => eprintln!("recv error: {}", e),
        }
    }   
}   

async fn do_server() -> Result<(), Box<dyn Error>> {
    let srv = UdpSocket::bind("0.0.0.0:8080").await?;
    let client: SocketAddr = "127.0.0.1:8000".parse()?;
    let mut seq = 0;
    loop {
        let _ = srv.send_to(format!("seq: {}", seq).as_bytes(), &client).await;
        sleep(Duration::from_millis(1000)).await;
        seq += 1;
    }
}

Run the server first, in background, then run the client.

Thank you I have run it and it worked very well. Problem is that I already started from a basic example and expanded from it. To be precise I think my problem stems from the debouncer where I dont find a way to clone the socket .

See below schema

client bind to a port and bind to server
udp packets (with file bytes) sent from client 
server receives the bytes and request missing packets to client
/!\
client process message from server to resend packets

So its between those twos that I fail, but when I look at my code, even with the println, it is hard to understand why its not working.

Edit: I found that the culprit was because of the second socket (socket_out) being created but not connected. My problem is that I cannot use the former arc socket in the generator function. If I comment this line the programs compile but my goal is exactly to be able to send the message.

If I uncomment and move let thread_socket = arc.clone(); before 'let _debouncer' then I have this error message (that is driving me nuts):

error[E0382]: borrow of moved value: `thread_socket`
   --> src/server/bin/main.rs:220:18
    |
165 |   let thread_socket = arc.clone();
    |       ------------- move occurs because `thread_socket` has type `std::sync::Arc<tokio::net::UdpSocket>`, which does not implement the `Copy` trait
166 |       let _debouncer = task::spawn(async move {
    |  _____________________________________________-
167 | |
168 | |         let duration = Duration::from_millis(1300);
169 | |
...   |
204 | |                         thread_socket.send_to(&*missing_chunks, ADDRESS_CLIENT).await; // arc_out.clone().send_to(&*missing_chunks, &peer...
    | |                         ------------- variable moved due to use in generator
...   |
216 | |         }
217 | |     });
    | |_____- value moved here
...
220 |       let result = thread_socket.recv_from(&mut buf).await;
    |                    ^^^^^^^^^^^^^ value borrowed here after move

error: aborting due to previous error

How could I enable Arc(socket) inside the generator function?

The error message is actually fairly clear here: You're attempting to use thread_socket on L220 after it was moved into the async move { and using it on L204. Arc does not implement Copy, so you have to clone it in this case. If you replace thread_socket with arc.clone() directly, it should work fine.

Actually yes and no, the problem was that I already had another clone, I found the fix: it was to have it in another scope with { }

I had a look at your updated code and the block is useless. The real fix was re-cloning it on L250.

1 Like

you are right, I just tested, indeed!

1 Like