【C++网络编程】(二)Linux平台下UDP客户/服务端程序

news2024/11/23 15:22:55

Linux平台下UDP客户/服务端程序

图片来源:https://subingwen.cn/linux/udp/

在这里插入图片描述

UDP服务器无法直接检测客户端断开连接。

UDP 服务端

server.cpp

#include <iostream>
#include <cstdlib>      // std::exit
#include <cstring>      // memset
#include <arpa/inet.h>  // socket, bind, recvfrom, sendto,SOCK_DGRAM
#include <unistd.h>     // close

int main()
{
    // 1. 创建 UDP 套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  // 创建一个UDP套接字
    if (sockfd == -1)
    {
        perror("socket");  // 错误处理
        std::exit(EXIT_FAILURE);
    }

    // 2. 将socket()返回值和本地的IP端口绑定到一起
    sockaddr_in addr;                     // 用于存储地址信息
    addr.sin_family = AF_INET;            // 地址族,IPv4
    addr.sin_port = htons(10000);         // 转换服务器的端口号10000为网络字节序
    addr.sin_addr.s_addr = INADDR_ANY;    // 绑定到任意IP地址
    // inet_pton(AF_INET, "172.31.108.107", &addr.sin_addr.s_addr); // 指定IP地址

    int ret = bind(sockfd, (sockaddr*)&addr, sizeof(addr)); // 绑定套接字到地址
    if (ret == -1)
    {
        perror("bind");  // 错误处理
        std::exit(EXIT_FAILURE);
    }

    // 3. 和客户端通信
    while (true)
    {
        char buf[1024];  // 接收缓冲区
        memset(buf, 0, sizeof(buf));  // 清零缓冲区
        
        sockaddr_in cliaddr;           // 用于存储客户端地址信息
        socklen_t clilen = sizeof(cliaddr); // 客户端地址结构的大小
        
        // 接收数据
        int len = recvfrom(sockfd, buf, sizeof(buf), 0, (sockaddr*)&cliaddr, &clilen); // 从客户端读取数据
        if (len > 0)
        {
            std::cout << "客户端: " << buf << std::endl;  // 打印客户端发送的消息

            // 回复客户端
            std::string response = "你好, 客户端...\n";
            sendto(sockfd, response.c_str(), response.size(), 0, (sockaddr*)&cliaddr, clilen); // 发送响应
        }
        else
        {
            perror("recvfrom");  // 错误处理
            break;
        }
    }

    close(sockfd);  // 关闭UDP套接字

    return 0;
}

编译与运行

g++ server.cpp -o server
./server

UDP 客户端

client.cpp

#include <iostream>
#include <cstdlib>      // std::exit
#include <cstring>      // memset, strlen
#include <arpa/inet.h>  // socket, sendto, recvfrom, inet_pton, htons
#include <unistd.h>     // close, sleep

int main()
{
    // 1. 创建通信的套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  // 创建一个UDP套接字
    if (sockfd == -1)
    {
        perror("socket");  // 错误处理
        std::exit(EXIT_FAILURE);
    }

    // 2. 准备服务器地址信息
    sockaddr_in addr;               // 用于存储服务器地址信息
    addr.sin_family = AF_INET;      // 地址族,IPv4
    addr.sin_port = htons(10000);   // 大端端口转换
    inet_pton(AF_INET, "172.31.108.107", &addr.sin_addr.s_addr); // 将IP地址转换为网络字节顺序

    // 3. 和服务器端通信
    int number = 0;
    while (true)
    {
        // 发送数据
        char buf[1024];                 // 数据缓冲区
        sprintf(buf, "你好, 服务器...\n", number++);  // 格式化字符串
        sendto(sockfd, buf, strlen(buf), 0, (sockaddr*)&addr, sizeof(addr));  // 发送数据
        
        // 接收数据
        memset(buf, 0, sizeof(buf));  // 清空缓冲区
        sockaddr_in recv_addr;         // 用于存储服务器地址信息
        socklen_t addr_len = sizeof(recv_addr);
        int len = recvfrom(sockfd, buf, sizeof(buf), 0, (sockaddr*)&recv_addr, &addr_len);  // 从服务器读取数据
        if (len > 0)
        {
            std::cout << "服务器: " << buf;   // 打印服务器发送的消息
        }
        else
        {
            perror("recvfrom"); 
            break;
        }
        sleep(1);   // 每隔1秒发送一条数据
    }

    close(sockfd);  // 关闭套接字

    return 0;
}

编译与运行

g++ client.cpp -o client
./client

相关头文件介绍

使用到的函数和宏除了<sys/socket.h>recvfromsendtoSOCK_DGRAM,其他使用到的函数和宏与TCP网络通信中的基本一致。

<sys/socket.h>

  • bytes_sent = recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);:用于接收数据报文,适用于无连接的套接字(如 UDP)。它允许从任何源地址接收数据。成功时返回接收到的字节数,失败时返回 -1。 参数:

    • sockfd:接收数据的套接字描述符。
    • buf:指向接收数据的缓冲区。
    • len:缓冲区的长度,表示最大接收字节数。
    • flags:接收选项的标志,通常为 0
    • src_addr:指向 sockaddr 结构体的指针,用于存储发送方的地址信息。
    • addrlen:指向 socklen_t 类型的指针,表示 src_addr 结构体的长度。
  • bytes_sent = sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen):用于发送数据报文,适用于无连接的套接字(如 UDP)。它允许将数据发送到指定的目标地址。成功时返回实际发送的字节数,失败时返回 -1。 参数:

    • sockfd:发送数据的套接字描述符。
    • buf:指向要发送数据的缓冲区。
    • len:要发送的字节数。
    • flags:发送选项的标志,通常为 0
    • dest_addr:指向目标地址的 sockaddr 结构体。
    • addrlen:目标地址的长度。
  • SOCK_DGRAM:用于创建数据报套接字,表示使用无连接的 UDP 协议进行数据传输。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2202929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在线制作PPT图表!这个好用轻量的ppt软件值得推荐!

ppt图表怎么制作&#xff1f; ppt是一种可以承载多种内容形式的媒介&#xff0c;我们在一个ppt页面中添加文本、形状、图片、视频、图表、思维导图等&#xff0c;对于其中的图表&#xff0c;在ppt中应该怎么制作呢&#xff1f; Office Powerpoint是很多人非常熟悉的演示软件&…

【宽搜】5.leetcode 199 二叉树的右视图

1 题目描述 题目链接&#xff1a;二叉树的右视图 2 题目解析 思路&#xff1a; 可以运用 层序遍历&#xff0c; 将每一层的结点值存入到vector< int >中&#xff0c;然后对每一层的vector&#xff0c;将vector的最后一个值加入到结果的vector中去 层序遍历的模板可以…

选择三品软件作为合作伙伴,确保PLM系统成功实施和长期稳定运行

企业在初次实施PLM&#xff08;Product Lifecycle Management&#xff0c;产品生命周期管理&#xff09;系统时&#xff0c;需要细致规划和充分准备。 一、明确需求和目标 战略对齐&#xff1a;首先&#xff0c;企业需要明确PLM系统如何与企业的长期战略相匹配&#xff0c;比如…

Python和C++的差异在哪里

1.编程应用领域 C&#xff1a;广泛应用于系统级开发、嵌入式系统、游戏开发等领域。C的底层控制和高性能使其成为这些领域的理想选择。 Python&#xff1a;广泛应用于数据科学、Web开发、人工智能等领域。Python的简洁语法和强大库支持使其成为这些领域的首选语言。 2.语法风…

基于Arduino的智能避障小车的控制方法

一.工作原理 上图为超声波模块转动角度与探测方向的关系&#xff0c;正常情况下&#xff0c;智能小车会沿直线行驶&#xff0c;当遇到前方有障碍物且小于一定距离时&#xff08;设定距离可根据具体情况调整&#xff09;&#xff0c;智能小车立即停止运行。舵机转动超声波模块探…

精益生产现场管理和改善:从知识到实操的落地

在制造业的广阔天地中&#xff0c;精益生产作为一种追求浪费最小化、效率最大化的生产管理模式&#xff0c;已成为众多企业转型升级的关键路径。本文&#xff0c;深圳天行健企业管理咨询公司将从精益生产现场管理和改善的理论知识出发&#xff0c;深入探讨其从理念导入到实操落…

Windows10如何关闭自动更新

1. 右键"此电脑"&#xff0c;选择"管理"。 2. 选择"服务和应用程序 > 服务"、然后找到"Windows Update"双击打开 3. 在"常规"选项卡下&#xff0c;把启动类型改为 "禁用" 4. 点击"恢复"选项卡&…

AGI|如何构建一个RAG应用?入门新手攻略!

目录 一、概述 二、过程概述 三、如何优化提问&#xff1f; 四、路由和高级查询 五、丰富索引结构 六、重排序上下文 七、总结 一、概述 Retrieval Augmented Generation RAG 检索增强的内容生成。 从字面上来看检索只是一种手段途径&#xff0c;在人工智能领域中存在多种…

【解决】虚拟机VMTool安装程序无法继续,Microsoft Runtime DLL安装程序未能完成安装

这个问题的原因是系统安装服务没有开启 打开任务管理器-服务-打开服务 找到windows installer 服务&#xff0c;开启即可

leetcode-85. 最大矩形

题目描述 给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵&#xff0c;找出只包含 1 的最大矩形&#xff0c;并返回其面积。 示例 1&#xff1a; 输入&#xff1a;matrix [["1","0","1","0","0"],["1&…

【Cursor教程】探索Cursor颠覆编程体验的创新工具!教程+示例+快捷键

文章目录 Cursor的全新定义Cursor的灵活订阅模式使用Cursor轻松创建支付页面Cursor的快捷键使用指南Cursor的未来展望Cursor的实际应用案例案例一&#xff1a;快速原型开发示例 案例二&#xff1a;教育培训示例 案例三&#xff1a;企业内部工具开发示例 更多的选择结语 在当今技…

turtlebot3使用

roslaunch turtlebot3_gazebo turtlebot3_house.launch roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch roslaunch turtlebot3_navigation turtlebot3_navigation.launch map_file:/home/hou/maps/housemap/map.yaml 以下为melodic版本 其他版本的ros命令有区别 …

SQL优化 where谓词条件OR优化

1.测试表&#xff0c;及测试语句where条件中OR对应两个字段选择度很高 create table t618 as select * from dba_objects; select object_name from t618 where (object_id12043 or DATA_OBJECT_ID12043) and STATUSVALID; 2.没有索引情况下&#xff0c;全表扫描逻辑读…

vue项目中使用drive.js元素未定位成功

在使用drive.js时&#xff0c;button我设了一个id 但是在使用时却定位失败 只要在mounted设置setTimeout即可

算法-依据先序遍历和中序遍历构建二叉树

简单的二叉树遍历算法&#xff0c; 为了通过给定的先序遍历&#xff08;preorder&#xff09;和中序遍历&#xff08;inorder&#xff09;数组构造二叉树&#xff0c;我们需要理解这两种遍历方式的特点&#xff1a; 先序遍历&#xff08;Preorder&#xff09;&#xff1a;首先…

基于SpringBoot+Vue+MySQL的药品信息管理系统

系统展示 管理员界面 医生界面 员工界面 系统背景 随着医疗技术的不断提升&#xff0c;药品在治疗疾病中扮演着越来越重要的角色。传统的药品管理方式以人工方式为主&#xff0c;但人工管理难以满足现代社会快速发展的需求。因此&#xff0c;需要一种更加高效、便捷的信息化管理…

作为一个直播运营,需要关注哪些数据指标?

在直播电商这一高度竞争且日新月异的行业中&#xff0c;作为直播运营的专业人士&#xff0c;若未能充分利用先进工具并紧密关注一系列核心数据指标&#xff0c;将难以推动直播间的持续成长与突破&#xff0c;且在达到一定规模后极易陷入停滞不前的困境。 本人在直播带货领域深耕…

Redis数据结构和使用场景

背景 Redis提供了丰富且结构简单的数据结构类型&#xff0c;在开发中被大量使用&#xff0c;接下来就来盘点下Redis的各种常用数据结构&#xff0c;以及他们的内部编码实现和使用场景。 数据结构 String 字符串类型是Redis最基础的数据结构。首先键都是字符串类型&#xff0c…

Bootstrap 5 练习 - 显示工具提示

文章目录 引言准备工作创建HTML文件导入Bootstrap 5框架编写页面代码编写JavaScript脚本浏览网页注意事项结束语 引言 大家好&#xff0c;今天我们将一起学习如何在Bootstrap 5中创建一个简单的工具提示&#xff08;Tooltip&#xff09;。工具提示是一个非常实用的用户界面元素…

常见大模型架构模式

以下是几种常见的大模型架构模式&#xff1a; 1. 路由分发架构模式 工作原理 当用户输入一个Prompt查询时&#xff0c;该查询会被发送到路由转发模块。路由转发模块对输入Prompt进行分类。如果Prompt查询是可以识别的&#xff0c;那么它会被路由到小模型进行处理。小模型通常具…