【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://www.mzph.cn/news/705282.shtml

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

相关文章

雾锁王国服务器配置怎么选择?阿里云和腾讯云

雾锁王国/Enshrouded服务器CPU内存配置如何选择&#xff1f;阿里云服务器网aliyunfuwuqi.com建议选择8核32G配置&#xff0c;支持4人玩家畅玩&#xff0c;自带10M公网带宽&#xff0c;1个月90元&#xff0c;3个月271元&#xff0c;幻兽帕鲁服务器申请页面 https://t.aliyun.com…

电商数据api接口大全,商品API,店铺API,订单API,获取请求key详细接入案例

电商数据API接口大全包括商品API、店铺API和订单API等&#xff0c;以下是一些常见的API接口以及获取请求key的详细接入案例&#xff1a; 获取请求key的详细接入案例&#xff1a; 以淘宝商品API为例&#xff0c;获取请求key的步骤如下&#xff1a; 注册成为开放平台的开发者&a…

GB28181 —— Ubuntu20.04下使用ZLMediaKit+WVP搭建GB28181流媒体监控平台(连接带云台摄像机)

最终效果 简介 GB28181协议是视频监控领域的国家标准。该标准规定了公共安全视频监控联网系统的互联结构, 传输、交换、控制的基本要求和安全性要求, 以及控制、传输流程和协议接口等技术要求,是视频监控领域的国家标准。GB28181协议信令层面使用的是SIP(Session Initiatio…

k8s节点负载使用情况分析命令kubectl describe node [node-name]

1.到任意安装了kubectl节点命令的节点上执行kubectl describe node [node-name] 上面的Requests最小分配 Limits最大分配是所有pod之和&#xff0c;最小分配之和不能超过服务器实际参数&#xff0c;否则新的pod会因为资源不够起不来&#xff0c;最大分配是预设之和&#xff0…

程序员眼中的“祖传代码”:魔法书中的智慧和技巧

目录 前言1 祖传代码的传承与传统2 家传宝贝&#xff1a;珍贵的遗产3 祖传秘方&#xff1a;独特的问题解决奥秘4 祖传代码中的故事&#xff1a;技术的发展轨迹结语 前言 在编程的奇妙世界中&#xff0c;存在着一种特殊的代码&#xff0c;被程序员们亲切地称之为“祖传代码”。…

Spring6学习技术|事务

学习材料 尚硅谷Spring零基础入门到进阶&#xff0c;一套搞定spring6全套视频教程&#xff08;源码级讲解&#xff09; 事务 什么是事务&#xff1f;好像是数据库部分的词&#xff0c;我自己的理解是对数据库进行的操作序列&#xff0c;要么一起完成&#xff0c;要么都不完成…

2024年AI行业专题报告:AI巨轮滚滚向前

2024年AI行业专题报告&#xff1a;AI巨轮滚滚向前。 1 Sora、Gemini 1.5 Pro 相继发布&#xff0c;AIGC 新时代已至 1.1 大模型 Sora 震撼登场&#xff0c;AI 生成视频领域里程碑 OpenAI 在 2024 年 2 月 16 日发布文生视频模型 Sora&#xff0c;突破了 AIGC 的高地&#xff0…

经营分析到底要做什么?

​做经营分析&#xff0c;不是只看数据这么简单&#xff0c;我们要从目标-分析-决策-预警&#xff0c;全流程实现。 基于数据中台底座&#xff0c;实现从制定战略目标到执行落地的数据应用闭环。主要从四个维度来做&#xff1a; 第一步&#xff0c;就是基于预算管理进行战略目…

Python中高效的爬虫框架,你用过几个?

在信息时代&#xff0c;数据是无价之宝。许多开发者和数据分析师需要从互联网上采集大量的数据&#xff0c;用于各种用途&#xff0c;如分析、建模、可视化等。Python作为一门强大的编程语言&#xff0c;提供了多种高效的爬虫框架&#xff0c;使数据采集变得更加容易和高效。本…

【Golang入门教程】Goland常用快捷键,看这一篇就够了 - 副本 (2)

开源软件的影响力 文章目录 开源软件的影响力 强烈推荐前言一、文件操作相关快捷键二、代码格式化相关的快捷键三、查找和定位相关的快捷键四、编辑代码相关的快捷键四、编辑器相关的快捷键总结强烈推荐专栏集锦写在最后 强烈推荐 前些天发现了一个巨牛的人工智能学习网站&…

力扣经典题目解析--搜索二维矩阵(小米一面)

原题地址: . - 力扣&#xff08;LeetCode&#xff09; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c…

数据隐私安全趋势

在当今社交媒体和开源开发的世界中&#xff0c;共享似乎已成为社会常态。毕竟&#xff0c;我们都被教导分享就是关怀。这不仅适用于个人&#xff0c;也适用于公司&#xff1a;无论是有意在社交媒体帐户和公司网站上&#xff0c;还是无意中通过员工的行为&#xff0c;公司可能会…

部署VUE+SpringBoot+nginx项目

本文是前端是vite element-plus 后端 springBoot 部署整个项目主要分为3个步骤&#xff0c; 1. 部署nginx&#xff0c;主要是配置nginx.conf 2.打包前端代码 3.打包后端代码 1.安装nginx 安装手顺&#xff1a; linux安装nginx_linux安装nginx需要gcc还是gcc-c-CSDN…

学生个性化成长平台搭建随笔记

1.Vue的自定义指令 在 Vue.js 中&#xff0c;我们可以通过 Vue.directive() 方法来定义自定义指令。具体来说&#xff0c;我们需要传递两个参数&#xff1a; 指令名称&#xff1a;表示我们要定义的指令名称&#xff0c;可以是一个字符串值&#xff0c;例如&#xff1a;has-rol…

【MySQL】undo log、redo log、bin log三者之间的区分?

undo log、redo log、bin log三者之间的区分&#xff1f; 从 产生的时间点、日志内容、用途 三方面展开论述即可 1.undo log——撤销日志 时间点&#xff1a;事务开始之前产生&#xff0c;根据当前版本的数据生成一个undo log&#xff0c;也保存在事务开始之前 作用&#xf…

在Pycharm中运行Django项目如何指定运行的端口

方法步骤&#xff1a; 打开 PyCharm&#xff0c;选择你的 Django 项目。在菜单栏中&#xff0c;选择 “Run” -> “Edit Configurations...”。在打开的 “Run/Debug Configurations” 对话框中&#xff0c;选择你的 Django server 配置&#xff08;如果没有&#xff0c;你…

Mathematica学习笔记收纳

笔记 可以关注官方公众号 帮助文件 https://reference.wolfram.com/language/index.html.zh 南京大学的介绍 https://oi.nju.edu.cn/Mathematica/listm.htm

08 string类的使用

为什么要学习string类 c语言中的字符串 c语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;c标准库提供了一些str系列的函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不符合OOP的思想&#xff0c;而且底层空间需要自…

Element复选框只要框不要字

场景 复选框分别放在多个选项后&#xff0c;只需要勾选框&#xff0c;不要展现的文字。 实现 <el-checkbox-group v-model"checkList"><el-checkbox label"使用核武器"></el-checkbox> </el-checkbox-group> ... data() {retu…

Leetcode——hot3最长连续序列

最长连续序列 class Solution {public int longestConsecutive(int[] nums) {if(nums.length 0 || nums.length 1){return nums.length;}Arrays.sort(nums);int count 1;int max 1;for(int i 0; i < nums.length - 1; i){if(nums[i1] - nums[i] 1){count;if(count &…