Linux网络编程- recvfrom() sendto()

recvfrom()

recvfrom() 函数是一个系统调用,用于从套接字接收数据。该函数通常与无连接的数据报服务(如 UDP)一起使用,但也可以与其他类型的套接字使用。与简单的 recv() 函数不同,recvfrom() 可以返回数据来源的地址信息。

函数原型为:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

参数解释:

  1. sockfd:一个已打开的套接字的描述符。

  2. buf:一个指针,指向用于存放接收到的数据的缓冲区。

  3. len:缓冲区的大小(以字节为单位)。

  4. flags:控制接收行为的标志。通常可以设置为0,但以下是一些可用的标志:

    • MSG_WAITALL:尝试接收全部请求的数据。函数可能会阻塞,直到收到所有数据。
    • MSG_PEEK:查看即将接收的数据,但不从套接字缓冲区中删除它【1】。
    • 其他一些标志还可以影响函数的行为,但在大多数常规应用中很少使用。
  5. src_addr:一个指针,指向一个 sockaddr 结构,用于保存发送数据的源地址。

  6. addrlen:一个值-结果参数。开始时,它应该设置为 src_addr 缓冲区的大小。当 recvfrom() 返回时,该值会被修改为实际地址的长度(以字节为单位)。

返回值:

  • 在成功的情况下,recvfrom() 返回接收到的字节数。
  • 如果没有数据可读或套接字已经关闭,那么返回值为0。
  • 出错时,返回 -1,并设置全局变量 errno 以指示错误类型。

例子:

struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
char buffer[1024];int bytes_received = recvfrom(sockfd, buffer, sizeof(buffer), 0,(struct sockaddr*)&sender, &sender_len);
if (bytes_received < 0) {perror("recvfrom failed");// handle error
}

在这个例子中,我们使用 recvfrom() 从套接字 sockfd 接收数据。发送者的地址和端口信息保存在 sender 结构中。

sendto()

sendto() 函数是一个系统调用,用于发送数据到一个指定的地址。它经常与无连接的数据报协议,如UDP,一起使用。不像 send() 函数只能发送数据到一个预先建立连接的远端,sendto() 允许在每次发送操作时指定目的地址。

函数原型为:

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

参数解释:

  1. sockfd:一个已打开的套接字的描述符。

  2. buf:一个指针,指向要发送的数据的缓冲区。

  3. len:要发送的数据的大小(以字节为单位)。

  4. flags:控制发送行为的标志。通常可以设置为0。一些可用的标志包括:

    • MSG_CONFIRM:在数据报协议下告诉网络层该数据已经被确认。
    • MSG_DONTROUTE:不查找路由,数据报将只发送到本地网络。
    • 其他标志可以影响函数的行为,但在大多数常规应用中很少使用。
  5. dest_addr:指向 sockaddr 结构的指针,该结构包含目标地址和端口信息。

  6. addrlendest_addr 缓冲区的大小(以字节为单位)。

返回值:

  • 成功时,sendto() 返回实际发送的字节数。
  • 出错时,返回 -1 并设置全局变量 errno 以指示错误类型。

例子:

struct sockaddr_in receiver;
receiver.sin_family = AF_INET;
receiver.sin_port = htons(12345);  // Some port number
inet_pton(AF_INET, "192.168.1.1", &receiver.sin_addr);  // Some IP addresschar message[] = "Hello, World!";
ssize_t bytes_sent = sendto(sockfd, message, sizeof(message), 0,(struct sockaddr*)&receiver, sizeof(receiver));
if (bytes_sent < 0) {perror("sendto failed");// handle error
}

在这个例子中,我们使用 sendto() 发送一个字符串到指定的IP地址和端口号。如果发送失败,我们打印一个错误消息。


注1

让我们通过一个简单的示例来展示如何使用MSG_PEEK标志来窥探套接字中的数据。

假设场景:我们正在编写一个简单的TCP服务器,该服务器接收客户端发送的消息。这些消息由一个头部开始,表示随后的数据长度。我们希望窥探这个头部,以便知道接下来应该读取多少数据。

假设消息头部长度固定为4字节,表示数据的长度。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>#define PORT 8080
#define HEADER_SIZE 4int main() {int server_socket, client_socket;struct sockaddr_in address;int addr_len = sizeof(address);char buffer[1024];// 创建TCP套接字server_socket = socket(AF_INET, SOCK_STREAM, 0);if (server_socket == -1) {perror("socket creation failed");exit(EXIT_FAILURE);}// 绑定套接字到指定的端口address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);if (bind(server_socket, (struct sockaddr*)&address, sizeof(address)) == -1) {perror("bind failed");close(server_socket);exit(EXIT_FAILURE);}// 开始监听if (listen(server_socket, 3) == -1) {perror("listen failed");close(server_socket);exit(EXIT_FAILURE);}printf("Waiting for a connection...\n");client_socket = accept(server_socket, (struct sockaddr*)&address, (socklen_t*)&addr_len);if (client_socket == -1) {perror("accept failed");close(server_socket);exit(EXIT_FAILURE);}printf("Connection established.\n");// 窥探消息头部int peek_len = recv(client_socket, buffer, HEADER_SIZE, MSG_PEEK);if (peek_len != HEADER_SIZE) {printf("Failed to peek header\n");close(client_socket);close(server_socket);exit(EXIT_FAILURE);}// 假设头部数据是一个整数,表示接下来的消息长度int message_len = *((int*)buffer);printf("Expected message length: %d\n", message_len);// 现在,可以根据消息长度读取整个消息close(client_socket);close(server_socket);return 0;
}

这只是一个简化的示例,实际应用中还需要考虑其他方面,如错误处理、多个客户端的处理、消息头和数据的解析等。


【1】若想了解sockaddr_in结构体,可移步到

     Linux网络编程- sockaddr & sockaddr_in & in_addr

【2】若想了解常用的网络编程函数,可移步到

     Linux- 网络编程初探

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

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

相关文章

scrapy爬虫系列之安装及入门介绍

前面介绍了很多Selenium基于自动测试的Python爬虫程序,主要利用它的xpath语句,通过分析网页DOM树结构进行爬取内容,同时可以结合Phantomjs模拟浏览器进行鼠标或键盘操作。但是,更为广泛使用的Python爬虫框架是——Scrapy爬虫。这是一篇在Windows系统下介绍 Scrapy爬虫安装及…

2023全新小红书图集和视频解析去水印网站源码

2023全新小红书图集和视频解析去水印网站源码 小红书视频图集解析网站源码&#xff0c;在红书看到好看的图片以及好看的头像&#xff0c;但是直接下载又有水印就非常难受&#xff0c;这个可以一键解析去除水印&#xff0c;支持统计解析次数&#xff0c;本地接口。 源码下载&a…

Django 数据库迁移(Django-04)

一 数据库迁移 数据库迁移是一种数据库管理技术&#xff0c;它用于在应用程序的开发过程中&#xff0c;根据模型&#xff08;Model&#xff09;的变化自动更新数据库结构&#xff0c;以保持数据库与代码模型的一致性。数据库迁移的主要目的是确保数据库与应用程序的模型定义同…

【C++】指针与引用(学习笔记)

一、左值与右值 左值&#xff1a;编译器为其单独分配了一块存储空间&#xff0c;可以取其地址的&#xff0c;可以放在赋值运算符左边 右值&#xff1a;数据本身。不能取到其自身地址&#xff0c;只能赋值运算右边 左值最常见的情况如西数和数据成员的名字 右值是没有标识符、…

【Linux常用命令4】系统状态监测命令---2

last&#xff1a;查看所有系统的登录记录 执行last命令时&#xff0c;它会读取/var/log目录下名称为wtmp的文件&#xff0c;并把该文件记录的登录系统或终端的用户名单全部显示出来。默认显示wtmp的记录&#xff0c;btmp能显示的更详细&#xff0c;可以显示远程登录&#xff0…

k8s 集群安装(vagrant + virtualbox + CentOS8)

主机环境&#xff1a;windows 11 k8s版本&#xff1a;v1.25 dashboard版本&#xff1a;v2.7.0 calico版本&#xff1a; v3.26.1 CentOS8版本&#xff1a;4.18.0-348.7.1.el8_5.x86_64 用到的脚本&#xff1a; https://gitcode.net/sundongsdu/k8s_cluster 1. Vagrant创建…

3d 贴图下载quixel

Quixel Megascans https://polyhaven.com/a/studio_small_03 Quixel Bridge&#xff1a;3D艺术家的宝库 在3D建模和渲染的世界中&#xff0c;找到高质量、适合项目的贴图素材至关重要。Quixel Bridge就是这样一个为3D艺术家提供大量免费贴图素材的资源库。在本文中&#xff…

2023去水印小程序源码修复版-前端后端内置接口+第三方接口

去水印小程序源码&#xff0c;前端后端&#xff0c;内置接口第三方接口&#xff0c;修复数据库账号密码错误问题&#xff0c;内置接口支持替换第三方接口&#xff0c;看了一下文件挺全的&#xff0c;可以添加流量主代码&#xff0c;搭建需要准备一台服务器&#xff0c;备案域名…

Spark 弹性分布式数据集 RDD

1.RDD简介 `RDD` 全称为 Resilient Distributed Datasets,是 Spark 最基本的数据抽象,它是只读的、分区记录的集合,支持并行操作,可以由外部数据集或其他 RDD 转换而来,它具有以下特性: 一个 RDD 由一个或者多个分区(Partitions)组成。对于 RDD 来说,每个分区会被一个…

论文阅读--Energy efficiency in heterogeneous wireless access networks

异构无线接入网络的能源效率 论文信息&#xff1a;Navaratnarajah S, Saeed A, Dianati M, et al. Energy efficiency in heterogeneous wireless access networks[J]. IEEE wireless communications, 2013, 20(5): 37-43. I. ABSTRACT && INTRODUCTION 本文提出了无…

【虚拟机栈】

文章目录 1. 虚拟机栈概述2. 局部变量表(Local Variables)3. 操作数栈4. 动态链接4.1 方法的调用&#xff1a;解析与分配 1. 虚拟机栈概述 每个线程在创建时都会创建一个虚拟机栈&#xff0c;其内部保存一个个的栈帧&#xff08;Stack Frame&#xff09;&#xff0c;对应着一次…

互联网Java工程师面试题·Redis 篇·第二弹

目录 16、Redis 集群方案什么情况下会导致整个集群不可用&#xff1f; 17、Redis 支持的 Java 客户端都有哪些&#xff1f;官方推荐用哪个&#xff1f; 18、Jedis 与 Redisson 对比有什么优缺点&#xff1f; 19、Redis 如何设置密码及验证密码&#xff1f; 20、说说 Redis…

【Vue】改变 vuex 中的 state ,子组件 watch 监听不到对象值变化。

文章目录 问题描述解决方法 问题描述 state 状态文件&#xff1a; export default {namespaced: true,state: {params: {aa: ,bb: [],}},mutations: {initParams(state) {state.params {aa: ,bb: [],};},},actions: {}, }父组件 <template> <child childParams&q…

CSS学习笔记

目录 1.CSS简介1.什么是CSS2.为什么使用CSS3.CSS作用 2.基本用法1.CSS语法2.CSS应用方式1. 内部样式2.行内样式3.外部样式1.使用 link标签 链接外部样式文件2.import 指令 导入外部样式文件3.使用举例 3.选择器1.基础选择器1.标签选择器2.类选择器3.ID选择器4.使用举例 2.复杂选…

【微服务】RedisSearch 使用详解

目录 一、RedisJson介绍 1.1 RedisJson是什么 1.2 RedisJson特点 1.3 RedisJson使用场景 1.3.1 数据结构化存储 1.3.2 实时数据分析 1.3.3 事件存储和分析 1.3.4 文档存储和检索 二、当前使用中的问题 2.1 刚性数据库模式限制了敏捷性 2.2 基于磁盘的文档存储导致瓶…

EasyX图形库note4,动画及键盘交互

大家好&#xff0c;这里是Dark Flame Master&#xff0c;专栏从这篇开始就会变得很有意思&#xff0c;我们可以利用今天所学的只是实现很多功能&#xff0c;同样为之后的更加好玩的内容打下基础&#xff0c;从这届开始将会利用所学的知识制作一些小游戏&#xff0c;废话不多说&…

基于支持向量机SVM和MLP多层感知神经网络的数据预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 一、支持向量机&#xff08;SVM&#xff09; 二、多层感知器&#xff08;MLP&#xff09; 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .…

bash命令——linux command

bash命令——linux command 1. Linux下的命令结构2. 重点命令学习2.1 基础命令2.2 文件操作2.3 文件权限2.4 目录操作2.5 环境变量2.6 进程信息2.7 grep命令2.8 awk命令2.9 cut命令2.10 bc命令2.11 sort命令 3. 其他知识点3.1 批量执行某条命令3.2 windows下载数据3.3 创建shel…

几种软件系统集成方式详细介绍

企业在信息化的过程中会根据自身的需求构建各种软件系统&#xff0c;如&#xff1a;网站、OA、CRM、订单系统、采购系统、库存管理、财务系统等&#xff0c;由于所需的软件系统一般是逐步构建和投入使用的&#xff0c;由于构建的时间和所采用的技术等不一样&#xff0c;软件系统…

高精度NTP时钟服务器(时间同步服务器)技术方案探讨

高精度NTP时钟服务器&#xff08;时间同步服务器&#xff09;技术方案探讨 高精度NTP时钟服务器&#xff08;时间同步服务器&#xff09;技术方案探讨 四分天下目前&#xff0c;全球的 GPS卫星同步系统处于“四分天下”状态&#xff0c;以美俄两国的系统处于领导地位&#xff…