Rust Udp组播:0 - 一个入门例子

系列文章目录


前言

实现Rust Udp组播。

一、项目创建

  1. cmd新建cargo工程目录
cargo new s1
  1. 切到s1目录新建两个子工程:udpclient,udpserver
cd s1
cargo new udpclient1
cargo new udpclient2
cargo new udpserver
  1. 修改s1目录下Cargo.toml添加子工程
[workspace]
members = ["tcpserver", "tcpclient1", "tcpclient2"]

在这里插入图片描述


二、Udp组播

  1. 编辑tcpclient1\src\main.rs,demo目录下执行命令cargo run -p tcpclient1
use std::net::UdpSocket;
use std::thread;

fn main() {
    let socket = UdpSocket::bind("127.0.0.1:1111").unwrap();
    const COUNT: usize = 100;
    loop {
        let buf = [0x41; COUNT];
        socket.send_to(&buf, "127.0.0.1:8888").unwrap();
        thread::sleep(std::time::Duration::from_millis(1000));
    }
}

  1. 编辑tcpclient2\src\main.rs,demo目录下执行命令cargo run -p tcpclient2
use std::net::UdpSocket;
use std::thread;

fn main() {
    let socket = UdpSocket::bind("127.0.0.1:2222").unwrap();
    const COUNT: usize = 100;
    loop {
        let buf = [0x41; COUNT];
        socket.send_to(&buf, "127.0.0.1:8888").unwrap();
        thread::sleep(std::time::Duration::from_millis(1000));
    }
}

  1. 编辑tcpserver\src\main.rs,demo目录下执行命令cargo run -p tcpserver
use std::net::{Ipv4Addr, UdpSocket};

fn main() {
    let socket = UdpSocket::bind("127.0.0.1:8888").unwrap();
    let multicast_addr = Ipv4Addr::new(234, 2, 2, 2);
    let inter = Ipv4Addr::new(0, 0, 0, 0);
    socket.join_multicast_v4(&multicast_addr, &inter).unwrap();

    let mut buf = [0u8; 65536];
    loop {
        let (amt, src) = socket.recv_from(&mut buf).unwrap();
        println!("{}: {:?}", amt, src);
    }
    socket.leave_multicast_v4(&multicast_addr, &inter).unwrap();
}
  1. 效果
    在这里插入图片描述

补充

  • 补充1:crossbeam的一些例子
  1. Cargo.toml添加依赖
[dependencies]
crossbeam = "0.8"
  1. main.rs
// 使用 crossbeam 库和 SegQueue 实现线程间的通信与数据同步
use crossbeam::{self, queue::SegQueue, scope};
use std::{thread, time::Duration};

fn main() {
    // 创建一个 SegQueue 实例用于线程间的数据传递
    let seg_queue = SegQueue::new();

    // 使用 crossbeam 的 scope 函数来创建一个作用域,内部可以并发执行多个任务
    scope(|s| {
        // 第一个任务:向队列中推入 0 到 9 的数字
        s.spawn(|_| {
            for i in 0..10 {
                seg_queue.push(i);
                println!("Thread 1: {}", i);
            }
        });

        // 第二个任务:从队列中弹出数据并打印,重复执行五次
        s.spawn(|_| {
            let mut i = 0;
            'outer: loop {
                while let Some(item) = seg_queue.pop() {
                    println!("Thread 2: {}", item);
                    i += 1;
                    if i >= 5 {
                        break 'outer;
                    };
                }
            }
        });
    })
    // 处理 scope 中的任务,如果有错误则.unwrap()会触发 panic
    .unwrap();

    // 主线程从队列中弹出剩余的数据并打印
    while let Some(item) = seg_queue.pop() {
        println!("Main Thread: {}", item);
    }
}
  1. 输出
Thread 1: 0
Thread 2: 0
Thread 2: 1
Thread 1: 1
Thread 1: 2
Thread 1: 3
Thread 1: 4
Thread 1: 5
Thread 1: 7
Thread 1: 8
Thread 1: 9
Thread 2: 2
Thread 2: 3
Thread 2: 4
Thread 2: 5
Main Thread: 6
Main Thread: 7
Main Thread: 8
Main Thread: 9
  • 补充2:udpsocket+crossbeam无锁队列+数据筛选
  1. udpserver.rs
use crossbeam::{self, queue::SegQueue, scope};
use std::net::{Ipv4Addr, UdpSocket};
use std::{thread, time::Duration};

fn main() {
    let socket = UdpSocket::bind("127.0.0.1:8888").unwrap();
    let multicast_addr = Ipv4Addr::new(234, 2, 2, 2);
    let inter = Ipv4Addr::new(0, 0, 0, 0);
    socket.join_multicast_v4(&multicast_addr, &inter).unwrap();

    let seg_queue = SegQueue::<u8>::new();
    scope(|s| {
        s.spawn(|_| loop {
            let mut buf = [0; 1024];
            let (number_of_bytes, _) = socket.recv_from(&mut buf).unwrap();
            for i in 0..number_of_bytes {
                seg_queue.push(buf[i]);
            }
        });
        s.spawn(|_| loop {
            let mut data = [0u8; 4];
            let mut d1 = 0u8;
            let mut d2 = 0u8;
            let mut index = 0;
            while let Some(item) = seg_queue.pop() {
                if index == 0 {
                    if item == 1u8 {
                        d1 = item;
                        index += 1;
                    } else {
                        continue;
                    }
                } else if index == 1 {
                    if item == 2u8 {
                        d2 = item;
                        data[0] = d1;
                        data[1] = d2;
                        index += 1;
                    } else {
                        index = 0;
                        continue;
                    }
                } else {
                    data[index] = item;
                    if index == 3 {
                        index = 0;
                        println!("receive: {:#?}", data);
                        continue;
                    }
                    index += 1;
                }
                thread::sleep(Duration::from_millis(5));
            }
        });
    })
    .unwrap();
    socket.leave_multicast_v4(&multicast_addr, &inter).unwrap();
}

  1. udpclient.rs
use std::net::UdpSocket;
use std::thread;

fn main() {
    let socket = UdpSocket::bind("127.0.0.1:1111").unwrap();
    const COUNT: usize = 10;
    loop {
        let mut buf = [0x41; COUNT];
        for i in 0..COUNT {
            buf[i] = (i + 1) as u8;
        }
        println!("send: {:#?}", buf);
        socket.send_to(&buf, "127.0.0.1:8888").unwrap();
        thread::sleep(std::time::Duration::from_millis(1000));
    }
}

  1. 效果

在这里插入图片描述

  • 补充3:数据流提取帧的一个算法
s.spawn(|_| {
            let mut data = [0u8; 5];
            let mut data_index = 0;

            loop {
                let mut buf = [0u8; 65535];
                let (number_of_bytes, _) = socket.recv_from(&mut buf).unwrap();
                let filled_buf = &mut buf[..number_of_bytes];
                
                for i in 0..number_of_bytes {
                    if data_index == 0 {
                        if filled_buf[i] == 0x1 {
                            data[data_index] = filled_buf[i];
                            data_index += 1;
                        }
                    } else if data_index == 1 {
                        if filled_buf[i] == 0x2 {
                            data[data_index] = filled_buf[i];
                            data_index += 1;
                        } else {
                            data_index = 0;
                        }
                    } else if data_index == 4 {
                        if filled_buf[i] == 0x5 {
                            data[data_index] = filled_buf[i];
                            println!("algrithm2:{:#?}", data);
                        }
                        data_index = 0;
                    } else {
                        data[data_index] = filled_buf[i];
                        data_index += 1;
                    }
                }
                

                //for i in 0..number_of_bytes {
                //    seg_queue.push(buf[i]);
                //}
            }
        });

总结

以上就是今天要讲的内容,本文仅仅简单介绍了rust Udp 组播的使用,而std::net提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 14
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值