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提供了大量能使我们快速便捷地处理数据的函数和方法。

### Java在计算机网络方面的应用场景 Java作为一种功能强大的编程语言,在计算机网络领域有着广泛的应用。以下是几个主要的应用场景: #### 1. **Socket 编程** Java 提供了丰富的 API 来支持基于 TCP 和 UDP 的 Socket 编程,这使得开发者能够轻松创建客户端-服务器应用程序。通过 `java.net` 包中的类,如 `ServerSocket`, `Socket`, `DatagramSocket` 等,可以实现高效的网络通信[^3]。 #### 2. **Web 开发** Java 在 Web 开发中占据重要地位,尤其是在企业级应用开发方面。Servlets, JSP (JavaServer Pages), Spring Boot 等框架和技术都极大地简化了 Web 应用程序的开发过程。这些技术允许开发者构建动态网页并处理 HTTP 请求和响应。 #### 3. **RESTful API 设计** 随着微服务架构的流行,设计 RESTful 风格的服务变得越来越普遍。使用诸如 Jersey 或者 Spring MVC 这样的框架可以帮助开发者快速搭建符合标准的 REST 接口,从而促进不同系统之间的数据交换。 #### 4. **分布式计算与大数据处理** Hadoop MapReduce 是一种流行的用于大规模数据分析的技术栈之一,而它是完全基于 Java 实现的。除此之外还有其他许多开源项目也采用了 Java 技术来解决复杂的分布式问题。 --- ### 关于学习资源 对于想要深入理解 Java 及其在网络环境下的运用的学习者来说,有以下几个方向可以选择: #### 官方文档 Oracle 官网提供了详尽的 Java SE 教程,其中包括专门针对网络编程的部分,这是最权威也是最适合初学者入门的地方。 #### 图书推荐 《Head First Network Programming》是一本非常实用且易于理解的书籍,它涵盖了从基础概念到高级主题的各种内容,并且以 Java 为例进行了详细的说明。 #### 在线课程平台 Coursera、Udemy 上有许多高质量的相关视频讲座可供选择;另外还可以关注一些专注于 IT 技能提升的知识分享社区比如 优快云 下载中心提供的免费教程包【Python、C++、Java、JS、Rust、Go语言入门完全手册】包含了大量关于各门主流编程语言的基础教学材料。 #### 社区交流 参与 GitHub 项目或者 Stack Overflow 讨论不仅能让你接触到最新的行业趋势,还能获得来自全球各地同行们的宝贵经验分享。 --- ### 示例代码:简单的 Echo Server 使用 Java 创建 下面是一个基本的例子展示如何用纯 Java 构建一个回声服务器(Echo Server),它可以接收来自客户端的消息并将相同的内容返回给发送方作为回应: ```java import java.io.*; import java.net.*; public class EchoServer { public static void main(String[] args) throws IOException { int port = 8080; try (ServerSocket serverSocket = new ServerSocket(port)) { System.out.println("Echo Server started on port " + port); while(true){ try(Socket clientSocket = serverSocket.accept(); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())) ){ String inputLine; while ((inputLine = in.readLine()) != null) { out.println(inputLine); // Send back the same message to client. } } catch(IOException e){ System.err.println(e.getMessage()); } } } } } ``` 此段代码展示了如何监听指定端口号上的连接请求,并读取/写入流来进行消息传递操作。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值