138|1

29

帖子

1

TA的资源

一粒金砂(中级)

《rust实战》简单的网络通信——TCP、UDP通讯的实现 [复制链接]

本帖最后由 ccccccc@ 于 2024-6-10 00:35 编辑

网络通信是现代应用程序的重要组成部分。本文将介绍如何使用Rust实现简单的TCP和UDP通讯。

实现TCP服务器和客户端

首先,我们实现一个简单的TCP服务器,它可以接收客户端的连接并回显收到的数据。

use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::thread;

fn handle_client(mut stream: TcpStream) {
    let mut buffer = [0; 512];
    while match stream.read(&mut buffer) {
        Ok(size) => {
            stream.write(&buffer[0..size]).unwrap();
            true
        },
        Err(_) => {
            println!("发生错误,终止连接");
            stream.shutdown(std::net::Shutdown::Both).unwrap();
            false
        }
    } {}
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
    println!("服务器已启动,等待连接...");
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                thread::spawn(|| handle_client(stream));
            },
            Err(e) => {
                println!("错误: {}", e);
            }
        }
    }
}

然后,实现TCP客户端,连接到服务器并发送和接收数据。

use std::net::TcpStream;
use std::io::{Read, Write};

fn main() {
    match TcpStream::connect("127.0.0.1:7878") {
        Ok(mut stream) => {
            let msg = b"你好,世界!";
            stream.write(msg).unwrap();
            let mut buffer = [0; 512];
            stream.read(&mut buffer).unwrap();
            println!("接收到: {}", String::from_utf8_lossy(&buffer));
        },
        Err(e) => {
            println!("无法连接到服务器: {}", e);
        }
    }
}

测试TCP通信

为了验证TCP服务器和客户端的功能,我们编写了以下测试用例。

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::TcpStream;
    use std::thread;
    use std::time::Duration;

    #[test]
    fn test_tcp_communication() {
        thread::spawn(|| {
            main();
        });

        thread::sleep(Duration::from_secs(1));

        let mut stream = TcpStream::connect("127.0.0.1:7878").unwrap();
        let msg = b"你好,世界!";
        stream.write(msg).unwrap();

        let mut buffer = [0; 512];
        stream.read(&mut buffer).unwrap();
        assert_eq!(&buffer[0..msg.len()], msg);
    }
}

图片.png  

实现UDP通信

我们实现一个简单的UDP客户端和服务器,发送和接收数据。

用户端:

use std::net::UdpSocket;

fn main() {
    let socket = UdpSocket::bind("127.0.0.1:34254").expect("无法绑定地址");
    socket.connect("127.0.0.1:4242").expect("无法连接到服务器");

    socket.send(b"你好,世界!").expect("发送数据失败");
    
    let mut buf = [0; 512];
    let (amt, src) = socket.recv_from(&mut buf).expect("接收数据失败");

    println!("从 {} 接收到: {}", src, String::from_utf8_lossy(&buf[..amt]));
}

服务端:

use std::net::UdpSocket;

fn main() {
    // 创建一个UDP套接字,并绑定到本地地址
    let socket = UdpSocket::bind("127.0.0.1:4242").expect("无法绑定地址");

    let mut buf = [0; 512];
    loop {
        // 接收来自客户端的消息
        let (amt, src) = socket.recv_from(&mut buf).expect("接收数据失败");

        // 打印接收到的数据和数据来源地址
        println!("从 {} 接收到: {}", src, String::from_utf8_lossy(&buf[..amt]));

        // 响应客户端的消息
        socket.send_to(b"Hello, Client!", &src).expect("发送数据失败");
    }
}

测试UDP通信

为了验证UDP通信的功能,为UDP服务器编写测试代码:

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::UdpSocket;

    #[test]
    fn test_udp_server() {
        // 创建一个UDP客户端
        let client_socket = UdpSocket::bind("127.0.0.1:0").expect("无法绑定客户端地址");

        // 启动UDP服务器
        std::thread::spawn(|| {
            super::main();
        });

        // 发送消息给服务器
        client_socket.send_to(b"你好,服务器!", "127.0.0.1:4242").expect("发送数据失败");

        // 接收来自服务器的响应消息
        let mut buf = [0; 512];
        let (amt, _) = client_socket.recv_from(&mut buf).expect("接收数据失败");

        // 验证服务器的响应消息
        assert_eq!(String::from_utf8_lossy(&buf[..amt]), "Hello, Client!");
    }
}

然后,我们为UDP服务器编写测试代码:

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::UdpSocket;

    #[test]
    fn test_udp_server() {
        // 创建一个UDP客户端
        let client_socket = UdpSocket::bind("127.0.0.1:0").expect("无法绑定客户端地址");

        // 启动UDP服务器
        std::thread::spawn(|| {
            super::main();
        });

        // 发送消息给服务器
        client_socket.send_to(b"你好,服务器!", "127.0.0.1:4242").expect("发送数据失败");

        // 接收来自服务器的响应消息
        let mut buf = [0; 512];
        let (amt, _) = client_socket.recv_from(&mut buf).expect("接收数据失败");

        // 验证服务器的响应消息
        assert_eq!(String::from_utf8_lossy(&buf[..amt]), "Hello, Client!");
    }
}

图片.png  

  图片.png  

易错点和注意事项

  1. 端口绑定冲突:确保服务器和客户端绑定的端口不冲突。
  2. 数据格式匹配:确保发送和接收的数据格式一致。
  3. 网络延迟处理:在测试中适当增加延迟以确保服务器启动完成。
此帖出自编程基础论坛

最新回复

感谢楼主分享的rust网络通信技术内容,对学习Rust语言帮助非常大,再次感谢   详情 回复 发表于 2024-6-11 11:37

回复
举报

633

帖子

5

TA的资源

纯净的硅(高级)

感谢楼主分享的rust网络通信技术内容,对学习Rust语言帮助非常大,再次感谢

此帖出自编程基础论坛

回复
您需要登录后才可以回帖 登录 | 注册

猜你喜欢
随便看看
查找数据手册?

EEWorld Datasheet 技术支持

推荐帖子
局域网网速变慢的故障细致分析

  计算机网络发生故障是不可避免的。网络故障诊断是网络管理的重要工作。一般当网络发生信息不通、不能浏览Web等连通性故 ...

研发的对口专业硕士参考薪资

2005年国内各大公司的薪酬一览     日本SONY(索尼) 1万/月,仅要研究生        韩国三星电子中国总部 25万/年      ...

QuartusII仿真警告信息原因解析

在QuartusII下进行编译和仿真的时候,会出现一堆warning,有的可以忽略,有的却需要注意,虽然按F1可以了解关于该警告的帮助,但有时 ...

DIY五路独立输出可调电源

经常用到各种用电设备的你,是不是总是为各种特殊规格的输出电源而头疼?今天DIYer就教你制作一款整合电源,不仅可以同时输出五 ...

【收藏】从android2.3.3到android4.2:最全的android系统源码下载大集合

本帖最后由 gooogleman 于 2014-3-19 11:47 编辑 115网盘下载,android源码大集合,包括2.3.3、2.3.4(新增)、2.3.5、2.3.7、4 ...

每周一题,放松心情,开阔思维

该数学问题不需要高级的数学理论来解决,可能是相当简单或者适度的困难 出题者已经有意地避开了特别简单或者困难的问题 然 ...

直播FAQ:基于迈来芯第二代位置传感器优化设计的新一代产品

直播主题:基于迈来芯第二代位置传感器优化设计的新一代产品,更高的性能和富有竞争力的成本 内容简介:本次研讨会,主要 ...

TI【LP_MSPM0L1306开发板】测评——热敏电阻控制LED以及RGB灯

热敏电阻采集温度信息并控制LED以及RGB 硬件组成 通过查看LaunchPad MSPM0L1306的原理图可知,热敏电路的原理图如图所示。 ...

STM32与PCF8563的逻辑电路

最近在做一个基于STM32的项目,使用了PCF8563的实时时钟芯片,以前用的是DS1307。 在替换RTC芯片后有两个问题: 1.P ...

大电流输出并联2个MOS管如何均流,MOS管所选封装是不是太小了?

看到一个汽车的PDU域控主板,上面有两路120A的输出是经过4个MOS管(用的是捷捷微电子的JMSH0601AGQ)背靠背2路并联实现的输出控 ...

关闭
站长推荐上一条 1/10 下一条

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表