Linux——网络(udp)
文章目录
目录
文章目录
前言
一、upd函数及接口介绍
1. 创建套接字 - socket 函数
2. 绑定地址和端口 - bind 函数
3. 发送数据 - sendto 函数
4. 接收数据 - recvfrom 函数
5. 关闭套接字 - close 函数
二、代码示例
1.服务端
2.客户端
总结
前言
Linux——网络基础(1)-CSDN博客
一、upd函数及接口介绍
1. 创建套接字 - socket 函数
#include <sys/socket.h>int socket(int domain, int type, int protocol);

- 参数说明:
domain:指定协议族,对于 UDP 编程,通常使用AF_INET表示 IPv4 协议族。type:指定套接字类型,对于 UDP,使用SOCK_DGRAM表示数据报套接字。protocol:指定具体的协议,一般设置为 0,让系统自动选择合适的协议(对于SOCK_DGRAM通常为 UDP)。
- 返回值:
- 成功时返回一个非负的套接字描述符;失败时返回 -1,并设置
errno以指示错误类型。
- 成功时返回一个非负的套接字描述符;失败时返回 -1,并设置
2. 绑定地址和端口 - bind 函数
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 参数说明:
sockfd:由socket函数返回的套接字描述符。addr:指向sockaddr结构体的指针,该结构体包含要绑定的地址和端口信息。对于 IPv4,通常使用sockaddr_in结构体,并进行强制类型转换。addrlen:addr结构体的长度。
- 返回值:
- 成功时返回 0;失败时返回 -1,并设置
errno。
- 成功时返回 0;失败时返回 -1,并设置
3. 发送数据 - sendto 函数
#include <sys/socket.h>ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

- 参数说明:
sockfd:套接字描述符。buf:指向要发送数据的缓冲区。len:要发送数据的长度。flags:发送标志,通常设置为 0。dest_addr:指向目标地址的sockaddr结构体指针,包含目标主机的地址和端口信息。addrlen:dest_addr结构体的长度。
- 返回值:
- 成功时返回实际发送的字节数;失败时返回 -1,并设置
errno。
- 成功时返回实际发送的字节数;失败时返回 -1,并设置
4. 接收数据 - recvfrom 函数
#include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
- 参数说明:
sockfd:套接字描述符。buf:指向用于存储接收数据的缓冲区。len:缓冲区的最大长度。flags:接收标志,通常设置为 0。src_addr:指向源地址的sockaddr结构体指针,用于存储发送方的地址和端口信息。addrlen:指向src_addr结构体长度的指针,调用前设置为该结构体的大小,调用后会被更新为实际接收到的地址信息的长度。
- 返回值:
- 成功时返回实际接收的字节数;失败时返回 -1,并设置
errno。
- 成功时返回实际接收的字节数;失败时返回 -1,并设置
5. 关闭套接字 - close 函数
#include <unistd.h>int close(int fd);
- 参数说明:
fd:要关闭的套接字描述符。
- 返回值:
- 成功时返回 0;失败时返回 -1,并设置
errno。
- 成功时返回 0;失败时返回 -1,并设置
二、代码示例
1.服务端
#pragma once#include <iostream>
#include <string>
#include <strings.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include "Log.hpp"// using func_t = std::function<std::string(const std::string&)>;
typedef std::function<std::string(const std::string&)> func_t;Log lg;enum{SOCKET_ERR=1,BIND_ERR
};uint16_t defaultport = 8080;
std::string defaultip = "0.0.0.0";
const int size = 1024;class UdpServer{
public:UdpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip):sockfd_(0), port_(port), ip_(ip),isrunning_(false){}void Init(){// 1. 创建udp socketsockfd_ = socket(AF_INET, SOCK_DGRAM, 0); // PF_INETif(sockfd_ < 0){lg(Fatal, "socket create error, sockfd: %d", sockfd_);exit(SOCKET_ERR);}lg(Info, "socket create success, sockfd: %d", sockfd_);// 2. bind socketstruct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_); //需要保证我的端口号是网络字节序列,因为该端口号是要给对方发送的local.sin_addr.s_addr = inet_addr(ip_.c_str()); //1. string -> uint32_t 2. uint32_t必须是网络序列的 // ??// local.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(sockfd_, (const struct sockaddr *)&local, sizeof(local)) < 0){lg(Fatal, "bind error, errno: %d, err string: %s", errno, strerror(errno));exit(BIND_ERR);}lg(Info, "bind success, errno: %d, err string: %s", errno, strerror(errno));}void Run(func_t func) // 对代码进行分层{isrunning_ = true;char inbuffer[size];while(isrunning_){struct sockaddr_in client;socklen_t len = sizeof(client);ssize_t n = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr*)&client, &len);if(n < 0){lg(Warning, "recvfrom error, errno: %d, err string: %s", errno, strerror(errno));continue;}inbuffer[n] = 0;std::string info = inbuffer;std::string echo_string = func(info);sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0, (const sockaddr*)&client, len);}}~UdpServer(){if(sockfd_>0) close(sockfd_);}
private:int sockfd_; // 网路文件描述符std::string ip_; // 任意地址bind 0uint16_t port_; // 表明服务器进程的端口号bool isrunning_;
};
Init方法用于初始化 UDP 服务器:- 调用
socket函数创建一个 UDP 套接字,使用AF_INET表示 IPv4 协议族,SOCK_DGRAM表示 UDP 套接字。 - 如果套接字创建失败,使用日志记录错误信息并退出程序。
- 创建一个
sockaddr_in结构体local,用于存储服务器的地址信息。 - 使用
bzero函数将local结构体清零。 - 设置
local结构体的sin_family为AF_INET,sin_port为传入的端口号,并使用htons函数将其转换为网络字节序。 - 使用
inet_addr函数将传入的 IP 地址字符串转换为网络字节序的 32 位整数,并赋值给sin_addr.s_addr。 - 调用
bind函数将套接字绑定到指定的地址和端口。 - 如果绑定失败,使用日志记录错误信息并退出程序。
- 调用
Run方法用于启动 UDP 服务器并处理客户端请求:- 将
isrunning_标志设置为true,表示服务器正在运行。 - 创建一个大小为
size的字符数组inbuffer,用于存储接收到的数据。 - 进入一个无限循环,不断接收客户端发送的数据。
- 调用
recvfrom函数接收客户端发送的数据,并将客户端的地址信息存储在client结构体中。 - 如果接收失败,使用日志记录错误信息并继续下一次循环。
- 在接收到的数据末尾添加字符串结束符
'\0',将其转换为std::string类型的info。 - 调用传入的函数对象
func对接收到的数据进行处理,并将处理结果存储在echo_string中。 - 调用
sendto函数将处理结果发送回客户端。
- 将
2.客户端
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>using namespace std;void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}// ./udpclient serverip serverport
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(0);}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);struct sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport); //?server.sin_addr.s_addr = inet_addr(serverip.c_str());socklen_t len = sizeof(server);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "socker error" << endl;return 1;}// client 要bind吗?要!只不过不需要用户显示的bind!一般有OS自由随机选择!// 一个端口号只能被一个进程bind,对server是如此,对于client,也是如此!// 其实client的port是多少,其实不重要,只要能保证主机上的唯一性就可以!// 系统什么时候给我bind呢?首次发送数据的时候string message;char buffer[1024];while (true){cout << "Please Enter@ ";getline(cin, message);// std::cout << message << std::endl;// 1. 数据 2. 给谁发sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&server, len);struct sockaddr_in temp;socklen_t len = sizeof(temp);ssize_t s = recvfrom(sockfd, buffer, 1023, 0, (struct sockaddr*)&temp, &len);if(s > 0){buffer[s] = 0;cout << buffer << endl;}}close(sockfd);return 0;
}
argc表示命令行参数的数量,argv是一个字符串数组,存储了命令行参数。- 如果命令行参数数量不等于 3(程序名、服务器 IP 地址、服务器端口号),则调用
Usage函数打印使用说明并退出程序。 - 从命令行参数中获取服务器的 IP 地址和端口号。
std::stoi函数将字符串类型的端口号转换为uint16_t类型。- 创建一个
sockaddr_in结构体server,用于存储服务器的地址信息。 bzero函数将server结构体的内存清零。server.sin_family设置为AF_INET,表示使用 IPv4 地址族。server.sin_port使用htons函数将端口号从主机字节序转换为网络字节序。server.sin_addr.s_addr使用inet_addr函数将字符串类型的 IP 地址转换为网络字节序的 32 位整数。len存储server结构体的大小。socket函数创建一个 UDP 套接字,使用AF_INET表示 IPv4 地址族,SOCK_DGRAM表示 UDP 协议。- 如果套接字创建失败,输出错误信息并返回 1。
- 创建一个
std::string类型的message用于存储用户输入的消息,创建一个字符数组buffer用于存储从服务器接收的数据。 - 使用
getline函数从标准输入读取用户输入的消息。 sendto函数将消息发送给服务器,指定套接字描述符、消息内容、消息长度、标志位、服务器地址结构体和地址结构体的大小。- 创建一个
sockaddr_in结构体temp用于存储服务器的地址信息,len存储temp结构体的大小。 recvfrom函数从服务器接收数据,指定套接字描述符、接收缓冲区、缓冲区大小、标志位、服务器地址结构体指针和地址结构体大小指针。- 如果接收到的数据长度大于 0,在缓冲区末尾添加字符串结束符
'\0',并输出接收到的数据。
总结
该程序实现了一个简单的 UDP 客户端,通过命令行参数指定服务器的 IP 地址和端口号,从用户输入获取消息并发送给服务器,同时接收服务器的响应并输出。客户端不需要显式绑定端口,操作系统会在首次发送数据时自动分配一个可用的端口。

相关文章:
Linux——网络(udp)
文章目录 目录 文章目录 前言 一、upd函数及接口介绍 1. 创建套接字 - socket 函数 2. 绑定地址和端口 - bind 函数 3. 发送数据 - sendto 函数 4. 接收数据 - recvfrom 函数 5. 关闭套接字 - close 函数 二、代码示例 1.服务端 2.客户端 总结 前言 Linux——网络基础…...
Oracle-Java JDBC 连接超时之后的认知纠正
背景 偶然读到熊老师的文章《老熊的三分地-JDBC中语句超时与事务》了解到:JAVA代码的最后正常断开数据库连接,在默认情况下,正常断开的数据库连接会自动提交没有提交的事务。 通过文章的测试JAVA程序,可以表明,JDB…...
自定义数据集使用框架的线性回归方法对其进行拟合
代码 import torch import numpy as np import torch.nn as nncriterion nn.MSELoss()data np.array([[-0.5, 7.7],[1.8, 98.5],[0.9, 57.8],[0.4, 39.2],[-1.4, -15.7],[-1.4, -37.3],[-1.8, -49.1],[1.5, 75.6],[0.4, 34.0],[0.8, 62.3]])x_data data[:, 0] y_data data…...
15天基础内容-5
day13 【String类、StringBuilder类】 主要内容 String类常用方法【重点】 String类案例【重点】 StringBuilder类【重点】 StringBuilder类常用方法【重点: append】 StringBuilder类案例【理解】 第一章String类 1.1 String类的判断方法 String类实现判断功能…...
82,【6】BUUCTF WEB .[CISCN2019 华东南赛区]Double Secret
进入靶场 提到了secret,那就访问 既然这样,那就传参看能不能报错 这个页面证明是有用的 传参长一点就会报错,传什么内容无所谓 所以网站是flask框架写的 有一个颜色深一点,点开看看 rc4加密url编码 import base64 from urllib…...
Android WebView 中网页被劫持的原因及解决方案
文章目录 一、原因分析二、解决方案一览三、解决方案代码案例3.1 使用 HTTPS3.2 验证 URL3.3 禁用 JavaScript3.4 使用安全的 WebView 设置3.5 监控网络请求3.6 使用安全的 DNS 四、案例深入分析4.1 问题4.2 分析 五、结论 在 Android 应用开发中,WebView 是一个常用…...
特朗普政府将开展新网络攻击
近日,特朗普政府已表态:减少物理战争,网络战将代替,以实现美国的全球优势。 特朗普也指示美国网络司令部可以在没有总统批准的情况下开展更广泛行动,尤其是应对一些突发事件,这其实成为了后续美国通过网络…...
快递代取项目Uniapp+若依后端管理
快递接单代取得uniappspringboot项目 实际效果图...
arcgis短整型变为长整型的处理方式
1.用QGIS的重构字段工具进行修改,亲测比arcgis的更改字段工具有用 2.更换低版本的arcgis10.2.2,亲测10.5和10.6都有这个毛病,虽然官方文档里面说的是10.6.1及以上 Arcgis10.2.2百度链接:https://pan.baidu.com/s/1HYTwgnBJsBug…...
06、Redis相关概念:缓存击穿、雪崩、穿透、预热、降级、一致性等
Redis相关概念:缓存击穿、雪崩、穿透、预热、降级、一致性等 Redis缓存雪崩、缓存击穿、缓存预热热点key、缓存降级、短链接、分布式锁秒杀、预减库存、 堆外缓存Redis架构设计、Redis动态刷新、Redis和DB双写一致性、过期删除策略、集群数据倾斜等一、缓存雪崩 缓…...
嵌入式基础 -- PCIe 控制器中断管理之MSI与MSI-X简介
PCIe 控制器中断管理技术文档 1. 背景 在现代计算机系统中,中断是设备与 CPU 通信的重要机制,PCIe 控制器提供了从传统线中断到基于消息的中断(MSI/MSI-X)的演进,以提升中断处理效率和可扩展性。x86 和 ARM 架构虽然…...
websocket实现
由于安卓资源管理器展示的路径不尽相同,各种软件保存文件的位置也不一定一样.对于普通用户上传文件时,查找文件可能是一个麻烦的事情.后来想到了一个办法,使用pc端进行辅助上传. 文章目录 实现思路1.0 实现定义web与客户端通信数据类型和数据格式web端websocket实现web端对客户…...
unity学习20:time相关基础 Time.time 和 Time.deltaTime
目录 1 unity里的几种基本时间 1.1 time 相关测试脚本 1.2 游戏开始到现在所用的时间 Time.time 1.3 时间缩放值 Time.timeScale 1.4 固定时间间隔 Time.fixedDeltaTime 1.5 两次响应时间之间的间隔:Time.deltaTime 1.6 对应测试代码 1.7 需要关注的2个基本…...
【C++】特殊类设计、单例模式与类型转换
目录 一、设计一个类不能被拷贝 (一)C98 (二)C11 二、设计一个类只能在堆上创建对象 (一)将构造函数私有化,对外提供接口 (二)将析构函数私有化 三、设计一个类只…...
scratch七彩六边形 2024年12月scratch三级真题 中国电子学会 图形化编程 scratch三级真题和答案解析
目录 scratch七彩六边形 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、…...
代码随想录刷题day16|(哈希表篇)349.两个数组的交集
目录 一、哈希表理论基础 二、集合set在哈希法中的应用 三、相关算法题目 四、相关知识点 1.set集合特点和常用方法 1.1 set集合概述 1.2 set集合特点 1.3 常用方法 2.set集合转换成数组 法1:另新建一个数组 法2:将结果集合转为数组 ▲ 3.数组…...
Synology 群辉NAS安装(6)安装mssql
Synology 群辉NAS安装(6)安装mssql 写在前面mssql 2019:成功安装说明,这个最终成功了 mssql 2022没有成功1. pull image2.启动mssql docker container 远程连接 写在前面 mssq是一个重要节点。 这是因为我对mysql没有一丝好感。虽然接触了许…...
2025年美赛B题-结合Logistic阻滞增长模型和SIR传染病模型研究旅游可持续性-成品论文
模型设计思路与创新点: 建模的时候应该先确定我们需要建立什么类的模型?优化类还是统计类?这个题需要大量的数据分析,因此我们可以建立一个统计学模型。 统计学建模思路:观察规律,建立模型,参…...
Hook 函数
什么是hook函数? 在计算机编程中,hook函数是指在特定的事件发生时被调用的函数,用于在事件发生前或后进行一些特定的操作。通常,hook函数作为回调函数被注册到事件处理器中,当事件发生时,事件处理器会自动…...
蓝桥杯模拟算法:蛇形方阵
P5731 【深基5.习6】蛇形方阵 - 洛谷 | 计算机科学教育新生态 我们只要定义两个方向向量数组,这种问题就可以迎刃而解了 比如我们是4的话,我们从左向右开始存,1,2,3,4 到5的时候y就大于4了就是越界了&…...
别再只盯着采样率了!用STM32H723的ADC做高精度FFT分析,这些坑我帮你踩过了
STM32H723高精度FFT实战:从ADC采样到频谱分析的工程化实现 频谱分析在工业振动监测、音频处理、电力系统谐波检测等领域有着广泛应用。STM32H723系列凭借其高性能ADC和浮点运算单元,为嵌入式实时频谱分析提供了硬件基础。但实际工程中,从ADC…...
工业协议通信开发实战:lib60870开源库完全指南
工业协议通信开发实战:lib60870开源库完全指南 【免费下载链接】lib60870 Official repository for lib60870 an implementation of the IEC 60870-5-101/104 protocol 项目地址: https://gitcode.com/gh_mirrors/li/lib60870 在工业自动化领域,设…...
自动驾驶轨迹预测新思路:VectorNet如何用矢量编码替代传统栅格化方法?
自动驾驶轨迹预测的矢量革命:VectorNet如何重构环境编码范式 在自动驾驶系统的决策闭环中,轨迹预测模块犹如驾驶员的预判能力,其准确性直接关系到行车安全与舒适性。传统基于卷积神经网络(CNN)的预测方法存在一个根本性…...
CST、Sspp与色散曲线的关联
CST cst Sspp 色散曲线在电磁仿真领域摸爬滚打过的工程师,对色散曲线这个磨人的小妖精应该都不陌生。今天咱们就来聊聊怎么用CST Studio Suite里的本征模求解器(Eigenmode Solver)提取波导结构的色散曲线,手把手带你从懵逼到上手…...
Java 新纪元 — JDK 25 + Spring Boot 4 全栈实战(十七):Boot 3 → Boot 4 迁移避坑指南——那些文档不会告诉你的迁移血泪史
系列导航 | ← 上一篇:D16 Spring Boot 4 + AI推理后端集成 | 下一篇:D18 云原生部署:Docker + K8s + GraalVM → 适用读者:正在从 Spring Boot 3.x 升级到 4.x 的开发者,或在评估升级可行性的架构师。 前置知识:熟悉 Spring Boot 3.x 开发,了解 JDK 21+ 基本特性。 本文…...
如何用Keep开源告警平台在15分钟内终结告警疲劳
如何用Keep开源告警平台在15分钟内终结告警疲劳 【免费下载链接】keep The open-source alerts management and automation platform 项目地址: https://gitcode.com/GitHub_Trending/kee/keep 你是否每天被数百条重复告警轰炸?运维团队是否在多个监控工具间…...
基于深度学习的桥梁健康状态监测与预警系统设计与实现
基于深度学习的桥梁健康状态监测与预警系统设计与实现 1. 系统总体架构 本系统采用 B/S 架构,由数据采集层、数据处理层、深度学习模型层、Web后端层及前端可视化层组成。 后端框架:Django (负责ORM、API、用户认证) 深度学习:TensorFlow 2.x / Keras (构建LSTM-Autoencod…...
Linux字符设备驱动开发与核心架构解析
Linux字符设备驱动开发深度解析1. Linux设备驱动分类与架构Linux内核将设备驱动分为三大类型:字符设备驱动:以字节流形式进行数据读写,如串口、键盘等块设备驱动:以固定大小数据块为单位进行操作,如硬盘、U盘等网络设备…...
Android Studio中文界面本地化指南:提升开发效率的全场景解决方案
Android Studio中文界面本地化指南:提升开发效率的全场景解决方案 【免费下载链接】AndroidStudioChineseLanguagePack AndroidStudio中文插件(官方修改版本) 项目地址: https://gitcode.com/gh_mirrors/an/AndroidStudioChineseLanguagePack And…...
VMware虚拟机部署Mirage Flow:多环境测试方案
VMware虚拟机部署Mirage Flow:多环境测试方案 为开发测试构建安全可靠的隔离环境 1. 环境准备与虚拟机配置 在开始部署Mirage Flow之前,我们需要先准备好合适的测试环境。使用VMware虚拟机是个不错的选择,它能为我们提供一个完全隔离的测试空…...

