使用有效的 C 代码将 struct sockaddr * 转换为 struct sockaddr_in6 * 的正确方法是什么?

2023-12-29

这是一个简单的程序,展示了我们通常如何类型转换struct sockaddr * to struct sockaddr_in * or struct sockaddr_in6 *在编写套接字程序时。

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main()
{
    struct addrinfo *ai;

    printf("sizeof (struct sockaddr): %zu\n", sizeof (struct sockaddr));
    printf("sizeof (struct sockaddr_in): %zu\n", sizeof (struct sockaddr_in));
    printf("sizeof (struct sockaddr_in6): %zu\n", sizeof (struct sockaddr_in6));

    if (getaddrinfo("localhost", "http", NULL, &ai) != 0) {
        printf("error\n");
        return EXIT_FAILURE;
    }

    if (ai->ai_family == AF_INET) {
        struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
        printf("IPv4 port: %d\n", addr->sin_port);
    } else if (ai->ai_family == AF_INET6) {
        struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
        printf("IPv6 port: %d\n", addr->sin6_port);
    }

    return 0;
}

Beej 的网络编程指南 http://beej.us/guide/bgnet/output/print/bgnet_A4.pdf第 10 页也推荐了此内容。

为了处理 struct sockaddr,程序员创建了一个并行结构:struct sockaddr_in(“in”代表“Internet”)与 IPv4 一起使用。

这是重要的一点:指向 struct sockaddr_in 的指针可以转换为指向 struct sockaddr 的指针,反之亦然。因此,即使 connect() 需要一个 struct sockaddr*,您仍然可以使用 struct sockaddr_in 并在最后一刻强制转换它!

但从讨论来看另一个问题 https://stackoverflow.com/q/39425409/1175080,看来这只是一个 hack,不是符合 C 标准的有效 C 代码。

特别是,请参阅安特的回答 https://stackoverflow.com/a/39425915/1175080其中提到,

至于流行的 struct sockaddr *、struct sockaddr_in * 和 struct sockaddr_in6 * 之间的转换技术 - 这些只是与 C 语言无关的 hack。它们只是在实践中起作用,但对于 C 语言而言,该技术是无效的。

那么,如果我们用来进行套接字编程的技术(以及书籍中推荐的技术)无效,那么重写上述代码以使其成为符合 C 标准的有效 C 代码的有效方法是什么?


因此,如果我们进行套接字编程的方式(以及书籍推荐的方式)是一种 hack,那么重写上述代码以使其也是符合 C 标准的有效 C 代码的正确方法是什么?

TL;DR:继续执行您在示例中介绍的操作。

您提供的代码在语法上似乎是正确的。在某些情况下,它可能会也可能不会表现出未定义的行为。是否有效取决于人的行为getaddrinfo().

在 C 中,没有任何方法可以满足所有功能要求,并且比您提供的标准技术更好地防止未定义的行为。这就是为什么它是标准技术。这里的问题是该函数必须支持所有可以想象的地址类型,包括尚未定义的类型。它可以将套接字地址指针声明为void *,这不需要强制转换,但这实际上不会改变任何给定程序是否表现出未定义的行为。

就其本身而言,getaddrinfo()设计时正是考虑到了这种用法,所以它是its如果对结果使用预期的转换会导致不当行为,则会出现问题。而且,getaddrinfo()不是 C 标准库的一部分——它(仅)由 POSIX 标准化,POSIX 也合并了 C 标准。因此,仅根据 C 来分析该函数就表明了不适当的过度关注。尽管仅就 C 而言,强制转换引起了一些担忧,但您应该预料到,在getaddrinfo()和其他 POSIX 网络功能使用struct sockaddr *,转换为正确的特定地址类型并访问引用的对象会产生可靠的结果。

另外,我认为AnT对你的另一个问题的回答过于简单化并且过于消极。我正在考虑是否要写一个对比的答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用有效的 C 代码将 struct sockaddr * 转换为 struct sockaddr_in6 * 的正确方法是什么? 的相关文章

  • 是否可以使静态控件透明?

    我正在尝试实现一个静态控件 该控件刷新 更改文本 以响应每秒发生一次的某个事件 由于我不想每秒绘制整个客户区域 所以我决定使用静态控件 现在的问题是父窗口被蒙皮 这意味着它有自定义位图作为背景 而静态控件没有适应 所以我正在寻找使静态控件的
  • 如何使用 LINQ ForEach 更改 List

    我有一个List
  • gets 和 scanf 有什么区别?

    如果代码是 scanf s n message vs gets message 有什么区别 似乎两者都获取消息的输入 基本区别 参考您的特定场景 scanf 遇到一个时结束接受输入whitespace newline or EOF gets
  • 如何将 CroppedBitmap 转换为 BitmapImage

    我正在尝试将 CroppedBitmap 转换为 BitmapImage 编辑 不使用内存流 我尝试过直接转换它 似乎这不是一个选择 这应该没那么难 我正在尝试剪切 BitmapImage 的一部分 并创建一个仅包含新裁剪的 Bitmap
  • Java写入ByteArrayOutputStream内存泄漏

    我正在将图像字节写入ByteArrayOutputStream然后通过套接字发送它 问题是 当我这样做时 ImageIO write image gif byteArray 内存增加很多 有点内存泄漏 我用这个发送 ImageIO writ
  • 将标准库添加到C++ eclipse项目中

    一个 非常 新手 C 问题 有没有办法自动将标准库添加到 C eclipse 项目中 我安装了 CDT 主要功能插件 您可以手动添加 STL 标头的路径路径和符号 gt 包含选项卡 http help eclipse org galileo
  • 如何在 C++ 中从模板基类的构造函数调用模板超类的构造函数?

    我正在使用 sublimetext3 用 c 进行编程 我的程序有一个名为 Array 的超类和一个名为 IntArray 的子类 这两个类都是模板类 目前 我在编译该程序时遇到问题 它不断在我的 IntArray cpp 文件中给出错误
  • MVVM 同步集合

    是否有一种标准化方法可以将 Model 对象集合与 C 和 WPF 中匹配的 ModelView 对象集合同步 我正在寻找某种类 可以使以下两个集合保持同步 假设我只有几个苹果 并且可以将它们全部保存在内存中 换句话说 我想确保如果我将 A
  • ASP.NET 中的 thread.sleep

    我正在为我的网站模拟彗星实时馈送协议 因此在我的控制器中我添加 while nothing new before timeout Thread Sleep 1000 但我注意到添加此功能后整个网站变慢了 调试后我得出结论 当我打电话时Thr
  • 持续运行的 C# 代码 - 服务还是单独的线程?

    我有一个 NET 4 Web 应用程序 它有 3 个关联的独立项目 DAL BAL 和 UI 我正在使用实体框架进行数据库交互 我有代码循环遍历一堆数据库数据 根据找到的内容调用方法 然后更新数据库 我希望这段代码一直运行 同时 我希望用户
  • 解析通过asp:FileUpload上传的XML文件

    我有一个场景 用户将上传 XML 文件 我想将该文件添加到数据库中的表中 不过 困难的部分是我需要解析文件 然后将一些信息添加到一些不同的表中 显示如何获取 XML 文件的每个示例都使用 URI 来获取文件 但是如何直接从数据库获取文件 或
  • 除法时的小数舍入误差 (C#)

    我基本上有四个数字 比如 100 200 300 400 我需要计算概率为 100 100 200 300 400 200 100 200 300 400 等等在 当我使用小数数据类型来存储这些概率时 由于舍入问题 它们不会达到 1 在不使
  • 链接错误:xxx 已在 *****.LIB 中定义:: 究竟出了什么问题?

    Problem 我正在尝试使用一个名为DCMTK http dicom offis de dcmtk它使用了一些其他外部库 zlib libtiff libpng libxml2 libiconv 我已经从同一网站下载了这些外部库 LIB
  • Subsonic 3 ActiveRecord 嵌套选择导致 NotIn 错误?

    我有以下 Subsonic 3 0 查询 其中包含嵌套的 NotIn 查询 public List
  • 将 R 值传递给采用 L 值的函数时出现过载歧义

    我有 2 个重载函数 一个采用 L 值 另一个采用 R 值 目的是让该函数可以像这样调用 Obj obj foo obj OR foo Obj 所以 我写了2个重载函数 template
  • 在 C# 中为 ListBox 分配数据源时,如何从 ListBox 中删除所选项目?

    在 C 中为 ListBox 分配数据源时 如何从 ListBox 中删除所选项目 尝试删除时出现错误 设置 DataSource 属性后 无法修改项目集合 但是当我尝试从数据源 数据表 中删除项目时 它会抛出错误 因为 数据行不在当前行集
  • 64 位随机生成器种子

    我目前正在运行一个具有 8 个以上管道 线程 的多线程模拟应用程序 这些管道运行非常复杂的代码 该代码取决于种子生成的随机序列 然后该序列被归结为单个 0 1 我希望在将种子从主线程传递到处理管道后 这种 随机处理 具有 100 的确定性
  • 使用反射检测属性的访问修饰符类型

    我编写了一些代码来使用反射查看属性 我已经使用反射从类中检索了属性列表 但是我需要查明该财产是公共的还是受保护的 例如 public string Name get set protected int Age get set Propert
  • 如何以一对一/零关系更新员工和身份用户

    我正在尝试更新员工记录 也想更新身份用户 如果我先单独更新身份用户 例如 UserManager Update user Context Entry employee State System Data Entity EntityState
  • RC4 实现与 openssl 输出不匹配

    我的目标是在 C C 中实现 RC4 流密码 并确保它产生与使用时相同的输出openssl命令 按照伪代码维基百科 https en wikipedia org wiki RC4 该实现似乎有效 因为它可以加密和解密内容 但是 加密的输出与

随机推荐

  • 有没有办法在禁用按钮时防止文本变灰?

    当我将按钮设置为禁用时 文本变为灰色 之前为黑色 在我的窗口中 结果是当按钮被禁用时文本不可读 我翻遍了 NSButton NSButtonCell NSCell NSControl 的文档 但没有找到任何方法使文本保持黑色 你知道我该怎么
  • Kotlin编译器会编译java文件吗?

    我有一个包含 java 和 kt 文件的项目 Kotlin 编译器会同时编译 java 和 kt 文件 还是只编译我的 kt 文件 No kotlinc仅编译 Kotlin 文件 kt 混合语言项目需要将两者结合起来kotlinc and
  • Angular + VB.NET - 路由不起作用

    所以我正在开发一个使用 AngularJS 和用 VB NET 编写的 Web API 的项目 所有这些工作都很好 直到我们必须维护路由为止 以下代码来自我的 angularApp 它定义了路由 var angularApp angular
  • 如何在 Cloud Run 上使用 Stackdriver 日志记录

    我正在尝试让 stackdriver 日志记录在 Google Cloud Run 完全托管 中运行的简单 Go 应用程序正常工作 但在 CloudRun 日志中看不到 stackdriver 条目 我已经创建了最简单的演示应用程序 htt
  • 使用 minimax 进行 tic-tac-toe 游戏可以使用多少个线程?

    我们以 5x5 井字游戏为例 假设轮到我的人工智能了 然后 我做了 25 步 基本上每个单元格 当然 如果它是合法的 移动 为每次移动创建一个线程 总共 25 个线程 最多 在每次移动时调用 minimax 函数 然后当所有结果都来自每个线
  • Visual C++ 2008 Express 下载链接失效了? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我目前正在学习的编程课程使用 Visual C 2008 为了在家工作 我们可以选择获取 Express 版本 我在网站上找不到下载链接 微软的支持也
  • Android 地图 - 限制在 180 度

    我可以将 Google 地图 V2 Android 限制在 180 180 经度 如 iOS MapKit 吗 我不希望它环绕 因为我正在尝试实现 clusterin 算法 而 180 180 度分割会让它变得困难 我希望平移限制在红线处
  • AngularJS - 如何访问指令中 templateUrl 内定义的表单?

    我正在尝试访问指令内的表单以进行验证 因此我想访问 setPristine 但是 我似乎无法弄清楚如何获取使用 templateUrl 创建的表单 我有一个 plunker 在这里详细说明了这个问题 http plnkr co edit S
  • Java用奇怪的字符创建Redis键和内容

    我正在使用以下代码创建一个新的 Redis 密钥 和内容 private static final String KEY ESTADOS estados private HashOperations
  • 在没有管理员权限的 Windows 上安装 python 模块

    我的工作笔记本电脑没有管理员权限 我的机器上已经安装了python和pip 版本号如下 C Users banand AppData Local Programs Python Python36 Scripts gt python vers
  • VHDL:进程块内的多个上升沿检测

    我对 VHDL 以及一般的数字电路 还很陌生 我正在尝试使用 BCD 样式块实现两位数的计数器 该电路的外部有一些按钮 按下这些按钮时 会将感兴趣的数字加一 很像闹钟 这是一个异步操作 会在某种形式的编辑模式下发生 外部强制 我编写的代码在
  • 隐藏包中的实现文件

    我有一个名为spellnum 它可以用作命令行实用程序 它具有if name main 块 或者它可以像标准 Python 模块一样导入 该模块定义了一个名为Speller看起来像这样 class Speller object def in
  • Spring Boot启动后如何获取所有端点列表

    我有一个用 Spring Boot 编写的休息服务 我想在启动后获取所有端点 我怎样才能做到这一点 为此 我想在启动后将所有端点保存到数据库 如果它们尚不存在 并使用它们进行授权 这些条目将被注入到角色中 并且角色将用于创建令牌 您可以在应
  • 如何使用 NSubstitute 模拟 DbContext,然后添加/删除数据

    我需要模拟 EFDbContext I use 这里的方法 https stackoverflow com a 21075569 3959480而且效果很好 mock a DbSet var mockDbSet Substitute For
  • Laravel:如何从字符串而不是刀片文件创建渲染视图?

    我有一些 html soimething 表中的占位符 我想从这个自定义 html 中获取渲染视图 我想避免手动进行字符串替换 是否可以 注意 我看到了建议的问题 但最终找到了一种更简洁的方法来实现我的目标 所以我发布这个问题的答案 请保持
  • 如何将 RESTful Web 服务添加到 Joomla 1.5+ [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 非常简单的问题 Joomla1 5 有好的网络服务解决方案吗 我一直在搜索 只找到了对 Joomla
  • Maven 发布:prepare-with-pom 非交互式

    我正在尝试使用 Maven 发布一个项目 我的项目 POM 包含 SNAPSHOT 依赖项 因此为了自动执行发布 我想基于 maven release plugin 目标使用以下 Maven 命令 mvn release prepare w
  • 使用 scanf 的最大字符串长度 -> ANSI C

    I have define MAX STR LEN 100 我想投入scanf模式 这样我就可以控制字符串长度 scanf 100 n s sometext I tried scanf MAX STR LEN n s sometext sc
  • 使用 ggplot 对相关热图上的 x 轴进行排序

    我正在尝试使用 ggplot 创建相关热图 但我似乎无法控制 x 或 y 轴上变量的顺序 具体来说 ggplot 似乎尝试按顺序对变量进行排序 但仅对第一个数字进行操作 这是问题的一个简单示例 x1 lt c 1 2 3 4 5 6 6 7
  • 使用有效的 C 代码将 struct sockaddr * 转换为 struct sockaddr_in6 * 的正确方法是什么?

    这是一个简单的程序 展示了我们通常如何类型转换struct sockaddr to struct sockaddr in or struct sockaddr in6 在编写套接字程序时 include