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了就是越界了&…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...

