【Linux C | 网络编程】套接字选项、getsockopt、setsockopt详解及C语言例子

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
⏰发布时间⏰:2024-02-27 09:02:30

本文未经允许,不得转发!!!

目录

  • 🎄一、概述
  • 🎄二、Linux系统下套接字选项
  • 🎄三、getsockopt、setsockopt 函数
    • ✨3.1 getsockopt、setsockopt 函数介绍
    • ✨3.2 getsockopt、setsockopt 函数举例
  • 🎄四、常见的通用套接字选项
  • 🎄五、总结


在这里插入图片描述

🎄一、概述

在网络编程中,套接字选项经常需要用到,例如设置套接字缓冲区大小、设置套接字非阻塞等。在Linux中,与套接字选项相关的几个系统调用函数有:getsockoptsetsockoptfcntlioctl。其中,getsockoptsetsockopt函数只能用于套接字选项,也是本文要求重点掌握的两个函数,而fcntl在网络编程中,最常见的就是将套接字设置成非阻塞。


在这里插入图片描述

🎄二、Linux系统下套接字选项

下面两个图片是Linux系统下套接字选项汇总,级别分别有:SOL_SOCKET、IPPROTO_IP、IPPROTO_ICMPV6、IPPROTO_IPV6、IPPROTO_TCP、IPPROTO_SCTP;数据类型中,用{}来表示结构体,如:linger{}表示struct lingertimeval{}表示struct timevaltimeval{}表示struct timeval

1、套接字层和IP层的套接字选项汇总(见下图)
在这里插入图片描述

2、传输层的套接字选项汇总(见下图)
在这里插入图片描述


在这里插入图片描述

🎄三、getsockopt、setsockopt 函数

✨3.1 getsockopt、setsockopt 函数介绍

函数原型:

#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
  • 函数说明:getsockoptsetstockopt用于获取或设置文件描述符sockfd引用的套接字的选项。
  • 函数参数:
    • sockfd:要操作的文件描述符sockfd
    • level:级别,取值一般有:SOL_SOCKET、IPPROTO_IP、IPPROTO_ICMPV6、IPPROTO_IPV6、IPPROTO_TCP、IPPROTO_SCTP
    • optname:选项名;
    • optval:指向某个变量的指针,用来存放获取或设置的值;
    • optlen:指明 optval 参数指向的内存大小。
  • 返回值:成功返回 0 ,出错返回 -1。

✨3.2 getsockopt、setsockopt 函数举例

下面代码是《unix网络编程卷1》源码进行修改的,可以依次打印获取到的套接字选项默认值。

// sockopt.c 修改自 《unix网络编程卷1》源码
/* include checkopts1 */
/* *INDENT-OFF* */
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/tcp.h>		/* for TCP_xxx defines */union val {int				i_val;long				l_val;struct linger		linger_val;struct timeval	timeval_val;
} val;static char	*sock_str_flag(union val *, int);
static char	*sock_str_int(union val *, int);
static char	*sock_str_linger(union val *, int);
static char	*sock_str_timeval(union val *, int);struct sock_opts {const char	   *opt_str;int		opt_level;int		opt_name;char   *(*opt_val_str)(union val *, int);
} sock_opts[] = {{ "SO_BROADCAST",		SOL_SOCKET,	SO_BROADCAST,	sock_str_flag },{ "SO_DEBUG",			SOL_SOCKET,	SO_DEBUG,		sock_str_flag },{ "SO_DONTROUTE",		SOL_SOCKET,	SO_DONTROUTE,	sock_str_flag },{ "SO_ERROR",			SOL_SOCKET,	SO_ERROR,		sock_str_int },{ "SO_KEEPALIVE",		SOL_SOCKET,	SO_KEEPALIVE,	sock_str_flag },{ "SO_LINGER",			SOL_SOCKET,	SO_LINGER,		sock_str_linger },{ "SO_OOBINLINE",		SOL_SOCKET,	SO_OOBINLINE,	sock_str_flag },{ "SO_RCVBUF",			SOL_SOCKET,	SO_RCVBUF,		sock_str_int },{ "SO_SNDBUF",			SOL_SOCKET,	SO_SNDBUF,		sock_str_int },{ "SO_RCVLOWAT",		SOL_SOCKET,	SO_RCVLOWAT,	sock_str_int },{ "SO_SNDLOWAT",		SOL_SOCKET,	SO_SNDLOWAT,	sock_str_int },{ "SO_RCVTIMEO",		SOL_SOCKET,	SO_RCVTIMEO,	sock_str_timeval },{ "SO_SNDTIMEO",		SOL_SOCKET,	SO_SNDTIMEO,	sock_str_timeval },{ "SO_REUSEADDR",		SOL_SOCKET,	SO_REUSEADDR,	sock_str_flag },
#ifdef	SO_REUSEPORT{ "SO_REUSEPORT",		SOL_SOCKET,	SO_REUSEPORT,	sock_str_flag },
#else{ "SO_REUSEPORT",		0,			0,				NULL },
#endif{ "SO_TYPE",			SOL_SOCKET,	SO_TYPE,		sock_str_int },
//	{ "SO_USELOOPBACK",		SOL_SOCKET,	SO_USELOOPBACK,	sock_str_flag },
//	{ "IP_TOS",				IPPROTO_IP,	IP_TOS,			sock_str_int },
//	{ "IP_TTL",				IPPROTO_IP,	IP_TTL,			sock_str_int },
#ifdef	IPV6_DONTFRAG{ "IPV6_DONTFRAG",		IPPROTO_IPV6,IPV6_DONTFRAG,	sock_str_flag },
#else{ "IPV6_DONTFRAG",		0,			0,				NULL },
#endif
#ifdef	IPV6_UNICAST_HOPS{ "IPV6_UNICAST_HOPS",	IPPROTO_IPV6,IPV6_UNICAST_HOPS,sock_str_int },
#else{ "IPV6_UNICAST_HOPS",	0,			0,				NULL },
#endif
#ifdef	IPV6_V6ONLY{ "IPV6_V6ONLY",		IPPROTO_IPV6,IPV6_V6ONLY,	sock_str_flag },
#else{ "IPV6_V6ONLY",		0,			0,				NULL },
#endif
//	{ "TCP_MAXSEG",			IPPROTO_TCP,TCP_MAXSEG,		sock_str_int },
//	{ "TCP_NODELAY",		IPPROTO_TCP,TCP_NODELAY,	sock_str_flag },
#ifdef	SCTP_AUTOCLOSE{ "SCTP_AUTOCLOSE",		IPPROTO_SCTP,SCTP_AUTOCLOSE,sock_str_int },
#else{ "SCTP_AUTOCLOSE",		0,			0,				NULL },
#endif
#ifdef	SCTP_MAXBURST{ "SCTP_MAXBURST",		IPPROTO_SCTP,SCTP_MAXBURST,	sock_str_int },
#else{ "SCTP_MAXBURST",		0,			0,				NULL },
#endif
#ifdef	SCTP_MAXSEG{ "SCTP_MAXSEG",		IPPROTO_SCTP,SCTP_MAXSEG,	sock_str_int },
#else{ "SCTP_MAXSEG",		0,			0,				NULL },
#endif
#ifdef	SCTP_NODELAY{ "SCTP_NODELAY",		IPPROTO_SCTP,SCTP_NODELAY,	sock_str_flag },
#else{ "SCTP_NODELAY",		0,			0,				NULL },
#endif{ NULL,					0,			0,				NULL }
};
/* *INDENT-ON* */
/* end checkopts1 *//* include checkopts2 */
int main(int argc, char **argv)
{int					fd;socklen_t			len;struct sock_opts	*ptr;for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) {printf("%s: ", ptr->opt_str);if (ptr->opt_val_str == NULL)printf("(undefined)\n");else {switch(ptr->opt_level) {case SOL_SOCKET:
//			case IPPROTO_IP:
//			case IPPROTO_TCP:fd = socket(AF_INET, SOCK_STREAM, 0);break;
#ifdef	IPV6case IPPROTO_IPV6:fd = socket(AF_INET6, SOCK_STREAM, 0);break;
#endif
#ifdef	IPPROTO_SCTPcase IPPROTO_SCTP:fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);break;
#endifdefault:printf("Can't create fd for level %d\n", ptr->opt_level);}len = sizeof(val);if (getsockopt(fd, ptr->opt_level, ptr->opt_name,&val, &len) == -1) {printf("getsockopt error");} else {printf("default = %s\n", (*ptr->opt_val_str)(&val, len));}close(fd);}}return 0;
}
/* end checkopts2 *//* include checkopts3 */
static char	strres[128];static char	*
sock_str_flag(union val *ptr, int len)
{
/* *INDENT-OFF* */if (len != sizeof(int))snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);elsesnprintf(strres, sizeof(strres),"%s", (ptr->i_val == 0) ? "off" : "on");return(strres);
/* *INDENT-ON* */
}
/* end checkopts3 */static char	*
sock_str_int(union val *ptr, int len)
{if (len != sizeof(int))snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);elsesnprintf(strres, sizeof(strres), "%d", ptr->i_val);return(strres);
}static char	*
sock_str_linger(union val *ptr, int len)
{struct linger	*lptr = &ptr->linger_val;if (len != sizeof(struct linger))snprintf(strres, sizeof(strres),"size (%d) not sizeof(struct linger)", len);elsesnprintf(strres, sizeof(strres), "l_onoff = %d, l_linger = %d",lptr->l_onoff, lptr->l_linger);return(strres);
}static char	*
sock_str_timeval(union val *ptr, int len)
{struct timeval	*tvptr = &ptr->timeval_val;if (len != sizeof(struct timeval))snprintf(strres, sizeof(strres),"size (%d) not sizeof(struct timeval)", len);elsesnprintf(strres, sizeof(strres), "%ld sec, %ld usec",tvptr->tv_sec, tvptr->tv_usec);return(strres);
}

运行结果:
在这里插入图片描述

在这里插入图片描述

🎄四、常见的通用套接字选项

  • SO_BROADCAST:开启或禁止进程发送广播消息的能力。只有数据报套接字支持广播;
  • SO_KEEPALIVE:给一个TCP套接字设置保持存活(keep-alive)选项后,如果2小时内在该套接字的任一方向上都没有数据交换,TCP就自动给对端发送一个保持存活探测分节(keep-alive probe)。
  • SO_LINGER:本选项指定close函数对面向连接的协议(例如TCP和SCTP,但不是UDP)如何操作。默认操作是close立即返回,但是如果有数据残留在套接字发送缓冲区中,系统将试着把这些数据发送给对端。
  • SO_RCVBUF:获取或设置接收缓冲区大小。接收缓冲区被TCP、UDP和SCTP用来保存接收到的数据,直到由应用进程来读取;
  • SO_SNDBUF:获取或设置发送缓冲区大小。
  • SO_RCVLOWAT:接收低水位标记。让select函数返回“可读”时套接字接收缓冲区中所需的数据量。
  • SO_SNDLOWAT:发送低水位标记。让select函数返回“可写”时套接字发送缓冲区中所需的可用空间。
  • SO_REUSEADDR
    (1) SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将该端口用作它们的本地端口的连接仍存在。
    (2) SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。
    (3) SO_REUSEADDR允许单个进程捆绑同一端口到多个套接字上,只要每次捆绑指定不同的本地P地址即可。
    (4) SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口已绑定到某个套接字上时,如果传输协议支持,同样的IP地址和端口还可以捆绑到另一个套接字上。一般来说本特性仅支持UDP套接字。

在这里插入图片描述

🎄五、总结

👉本文介绍网络编程中的套接字选项,先是汇总了常见的套接字选项,然后介绍获取和设置套接字选项的函数getsockopt、setsockopt,并给出对应的C语言例子,最后列出几个常见的通用套接字选项。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

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

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

相关文章

浅谈门级驱动电压对IGBT性能的影响

绝缘门极双极型晶体管&#xff08;IGBT&#xff09;是复合了功率场效应管和电力晶体管的优点而产生的一种新型复合器件&#xff0c;具有输入阻抗高、工作速度快、热稳定性好、驱动电路简单、饱和压降低、耐压高电流大等优点&#xff0c;因此现今应用相当广泛。但是IGBT良好特性…

Programming Abstractions in C阅读笔记:p303-p305

《Programming Abstractions in C》学习第74天&#xff0c;p303-p305总结&#xff0c;总计3页。 一、技术总结 1.时间复杂度分类(complexity classes) ClassNotationExampleconstantO(1)Returning the first element in an arraylogarithmicO(logN)Binary search in a sorte…

使用Node.js开发一个文件上传功能

在现代 Web 应用程序开发中&#xff0c;文件上传是一个非常常见且重要的功能。今天我们将通过 Node.js 来开发一个简单而强大的文件上传功能。使用 Node.js 来处理文件上传可以带来许多好处&#xff0c;包括简单的代码实现、高效的性能和灵活的配置选项。 首先&#xff0c;我们…

【软件测试】--功能测试3

一、用例执行 说明&#xff1a;执行结果与用例的期望结果不一致&#xff08;含义&#xff09;&#xff0c;为缺陷。 执行失败的用例 提示&#xff1a;用例执行不通过为缺陷&#xff0c;需要进行缺陷管理 二、缺陷 2.1 定义 软件中存在的各种问题&#xff0c;都为缺陷&#…

第 1 章 微信小程序与云开发从入门到实践从零开始做小程序——开发认识微信小程序

小北的参考工具书 小程序开发的图书并不少&#xff0c;这本书仍然值得你拥有&#xff01; 首先&#xff0c;这是一本全栈小程序开发教程&#xff0c;循序渐进&#xff0c;由浅入深&#xff0c;介绍了小程序开发你想了解的方方面面&#xff0c;包括近其小程序开发的各种新技术应…

【HarmonyOS】鸿蒙开发之Stage模型-应用配置文件——第4.2章

Stage模型-应用配置文件 AppScope -> app.json5&#xff1a;应用的全局配置信息entry&#xff1a;OpenHarmony工程模块&#xff0c;编译构建生成一个HAP包 build&#xff1a;用于存放OpenHarmony编译生成的hap包src -> main -> ets&#xff1a;用于存放ArkTS源码src …

docker 常用指令(启动,关闭,查看运行状态)

文章目录 docker 常用指令启动 docker关闭 docker查看 docker的运行状态 docker 常用指令 启动 docker systemctl start docker关闭 docker systemctl stop docker查看 docker的运行状态 systemctl status docker如下图所示&#xff1a; 表示docker正在运行中

Stable Diffusion 绘画入门教程(webui)-ControlNet(NormalMap)

法线贴图NormalMap可以把参考图的光影分布关系,法线贴图可以实现在不改变物体真实结构的基础上也能反映光影分布的效果&#xff0c;被广泛应用在 CG 动画渲染和游戏制作等领域 简单来讲可以参考原图的光影明暗关系并还原原图姿态&#xff0c;如下图&#xff1a;左边为原图&…

opencv判断二值的情况

目的 先说说理论&#xff1a; 什么叫图像的二值化&#xff1f;二值化就是让图像的像素点矩阵中的每个像素点的灰度值为0&#xff08;黑色&#xff09;或者255&#xff08;白色&#xff09;&#xff0c;也就是让整个图像呈现只有黑和白的效果。在灰度化的图像中灰度值的范围为0…

IDEA的LeetCode插件的设置

一、下载插件 选择点击File->Setting->Plugins&#xff1a;搜索LeetCode 二、打开这个插件 选择View —>Tool Windows—>leetcode 三、登陆自己的账号 关于下面几个参数的定义&#xff0c;官方给的是&#xff1a; Custom code template: 开启使用自定义模板&…

小程序应用、页面、组件生命周期

引言 微信小程序生命周期是指在小程序运行过程中&#xff0c;不同阶段触发的一系列事件和函数。这一概念对于理解小程序的整体架构和开发流程非常重要。本文将介绍小程序生命周期的概念以及在不同阶段触发的关键事件&#xff0c;帮助开发者更好地理解和利用小程序的生命周期。 …

vscode输入英文时字体之间的间隔突然变大,似中文

vscode输入英文时字体之间的间隔突然变大&#xff0c;似中文 主要原因&#xff1a; 是由于输入法变成全角模式了。原因可能是不小心按了 shift空格键快捷键造成的。 正常情况&#xff0c;全角就是字母和数字等与汉字占等宽位置的字。 半角就是ASCII方式的字符&#xff0c;在没…

架构设计实践:熟悉架构设计方法论,并动手绘制架构设计图

文章目录 一、架构设计要素1、架构设计目标2、架构设计模式&#xff08;1&#xff09;分而治之&#xff08;2&#xff09;迭代式设计 3、架构设计的输入&#xff08;1&#xff09;概览&#xff08;2&#xff09;功能需求 - WH分析法&#xff08;3&#xff09;质量 - “怎么”分…

blender bvh显示关节名称

导入bvh&#xff0c;菜单选择布局&#xff0c;右边出现属性窗口&#xff0c; 在下图红色框依次点击选中&#xff0c;就可以查看bvh关节名称了。

机器学习YOLO操作全流程​​编

YOLO介绍 Ultralytics YOLOv8,是最新的著名实时目标检测和图像分割模型。它基于深度学习和计算机视觉的最新进展,提供了无与伦比的速度和精度性能。由于其精简的设计,适用于各种应用,并且可以轻松适配不同的硬件平台,从边缘设备到云端API。 探索 YOLOv8 文档,这是一个全…

Docker基础(一)

文章目录 1. 基础概念2. 安装docker3. docker常用命令3.1 帮助命令3.2 镜像命令3.3 容器命令3.4 其他命令 4. 使用案例 1. 基础概念 镜像&#xff08;Image&#xff09;&#xff1a;Docker 镜像&#xff08;Image&#xff09;&#xff0c;就相当于是一个 root 文件系统。比如官…

计算机网络——IPV4数字报

1. IPv4数据报的结构 本结构遵循的是RFC 791规范&#xff0c;介绍了一个IPv4数据包头部的不同字段。 1.1 IPv4头部 a. 版本&#xff08;Version&#xff09;&#xff1a;指明了IP协议的版本&#xff0c;IPv4表示为4。 b. 头部长度&#xff08;IHL, Internet Header Length&…

sql-labs第46关 order by盲注

sql-labs第46关 order by盲注 来到了第46关进入关卡发现让我们输入的参数为sort&#xff0c;我们输入?sort1尝试&#xff1a; 输入?sort2,3,发现表格按照顺序进行排列输出&#xff0c;明显是使用了order by相关的函数。 我们将参数变成1进行尝试&#xff0c;就会报错&…

flutter简单的MethodChannel通道Demo(引入调用小红书sdk)

flutter端创建MethodChannel类 import package:flutter/services.dart;//MethodChannel const methodChannel const MethodChannel(com.flutter.demo.MethodChannel);class FlutterMethodChannel {/** MethodChannel flutter给原生发信息* 在方法通道上调用方法invokeMethod*…

【服务器数据恢复】ext3文件系统下硬盘坏道掉线的数据恢复案例

服务器数据恢复环境&#xff1a; 一台IBM某型号服务器上有16块FC硬盘组建RAID阵列。上层linux操作系统&#xff0c;ext3文件系统&#xff0c;部署有oracle数据库。 服务器故障&检测&#xff1a; 服务器上跑的业务突然崩溃&#xff0c;管理员发现服务器上有2块磁盘的指示灯…