《TCP/IP网络编程》阅读笔记--getsockopt和setsockopt的使用

news2025/1/16 1:59:34

目录

1--Socket的多种可选项

2--getsocketopt()

3--setsockopt()

4--代码实例


1--Socket的多种可选项

        Socket 拥有多种可选项,其可分为 SOL_SOCKET 层,IPPROTO_IP 层和IPPROTO_TCP 层等,一般通过 getsocketopt() 和 setsockopt() 函数进行获取和设置;

2--getsocketopt()

#include <sys/socket.h>
int getsockopt(int sock, int level, int optname, void* optval, socklen_t* optlen);
// 成功时返回 0,失败时返回 -1
// sock 用于查看选项 socket 的文件描述符
// level 表示要查看的可选项的协议层
// optname 表示要查看的可选项名
// optval 表示保存查看结果的缓冲地址值
// optlen 表示向第四个参数 optval 传递的缓冲大小,调用函数后,该变量中保存通过第四个参数返回的可选项信息的字节数

3--setsockopt()

#include <sys/socket.h>
int setsockopt(int sock, int level, int optname, const void* optval, socklen_t optlen);
// 成功时返回 0,失败时返回 -1
// sock 用于更改可选项 socket 的文件描述符
// level 表示要更改的可选项的协议层
// optname 表示要更改的可选项名
// optval 表示保存更改的选项信息的缓冲地址值
// optlen 表示向第四个参数 optval 传递的可选项信息的字节数

4--代码实例

① 基于 getsockopt() 函数,利用设置协议层为 SOL_SOCKETSO_TYPE 可选项名来查看 SOCKET 的类型:

// gcc sock_type.c -o sock_type
// ./sock_type

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char* argv[]){
    int tcp_sock, udp_sock;
    int sock_type;
    socklen_t optlen;
    int state;

    optlen = sizeof(sock_type);
    tcp_sock = socket(PF_INET, SOCK_STREAM, 0); // create tcp socket
    udp_sock = socket(PF_INET, SOCK_DGRAM, 0); // create udp socket
    printf("SOCK_STREAM: %d \n", SOCK_STREAM);
    printf("SOCK_DGRAM: %d \n", SOCK_DGRAM);

    state = getsockopt(tcp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
    if(state){
        error_handling("getsockopt() error!");
    }
    printf("Socket type one: %d \n", sock_type);

    state = getsockopt(udp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
    if(state){
        error_handling("getsockopt() error!");
    }
    printf("Socket type two: %d \n", sock_type);

}

② 通过可选项名为 SO_SNDBUFSO_RCVBUF 来查看和设置 I/O 缓冲:

// gcc get_buf.c -o get_buf
// ./get_buf

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char* argv[]){
    int sock;
    int snd_buf, rcv_buf, state;
    socklen_t len;

    sock = socket(PF_INET, SOCK_STREAM, 0);
    len = sizeof(snd_buf);
    state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
    if(state){
       error_handling("getsockopt() error!"); 
    }

    len = sizeof(rcv_buf);
    state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
    if(state){
       error_handling("getsockopt() error!"); 
    }

    printf("Input buffer size: %d \n", rcv_buf);
    printf("Output buffer size: %d \n", snd_buf);
    return 0;    
}

// gcc set_buf.c -o set_buf
// ./set_buf

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char* argv[]){
    int sock;
    int snd_buf = 1024*3, rcv_buf = 1024*3;
    int state;
    socklen_t len;

    sock = socket(PF_INET, SOCK_STREAM, 0);
    state = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, sizeof(snd_buf));
    if(state){
       error_handling("getsockopt() error!"); 
    }

    state = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, sizeof(rcv_buf));
    if(state){
       error_handling("getsockopt() error!"); 
    }

    len = sizeof(snd_buf);
    state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
    if(state){
       error_handling("getsockopt() error!"); 
    }

    len = sizeof(rcv_buf);
    state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
    if(state){
       error_handling("getsockopt() error!"); 
    }

    printf("Input buffer size: %d \n", rcv_buf);
    printf("Output buffer size: %d \n", snd_buf);
    return 0; 
}

③ 通过更改 SO_REUSEADDR 的状态来将处于 Time-wait 状态的 SOCKET 端口号重新分配给新的 SOCKET:

// gcc reuseadr_eserver.c -o reuseadr_eserver
// ./reuseadr_eserver 9190

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define TRUE 1
#define FALSE 0

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char *argv[]){
    int serv_sock, clnt_sock;
    char message[30];
    int option, str_len;
    socklen_t optlen, clnt_adr_sz;
    struct sockaddr_in serv_adr, clnt_adr;

    if(argc != 2){
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }

    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    if(serv_sock == -1){
        error_handling("socket() error");
    }

    // set SO_REUSEADDR 
    optlen = sizeof(option);
    option = TRUE;
    setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&option, optlen);

    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family = AF_INET;
    serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_adr.sin_port = htons(atoi(argv[1]));

    if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){
        error_handling("bind() error");
    }

    if(listen(serv_sock, 5) == -1){
        error_handling("listen() error");
    }
    
    clnt_adr_sz = sizeof(clnt_adr);
    clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);

    while((str_len = read(clnt_sock, message, sizeof(message))) !=0){
        write(clnt_sock, message, str_len);
        write(1, message, str_len);
    }
    close(clnt_sock);
    close(serv_sock);
    return 0;
}

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

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

相关文章

【Cpolar内网穿透】公网SSH远程连接Termux – 电脑使用安卓Termux

目录 前言 1.安装ssh 2.安装cpolar内网穿透 3.远程ssh连接配置 4.公网远程连接 5.固定远程连接地址 前言 使用安卓机跑东西的时候&#xff0c;屏幕太小&#xff0c;有时候操作不习惯。不过我们可以开启ssh&#xff0c;使用电脑PC端SSH远程连接手机termux。 本次教程主要…

C#,《小白学程序》第二十课:大数(BigInteger)的四则运算之一,加法

大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算。 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法。 重复了部分 19 课的代码。 1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary>…

软件架构设计(十一) 软件产品线

1、基本概念 软件产品线是从DSSA(特定领域架构)扩展而来的,我们从事软件开发,当您有了多年的经验之后,往往会沉淀到某一个特定领域,然后做这个领域的行业软件。 此时,您会把一些共性的东西开发出来,稳定下来。如果以后再开发同类型的系统时,做一些小修小改或者应用层…

《Python趣味工具》——自制emoji(1)绘制爱心应援牌❤️

项目目标&#xff1a; 本项目旨在学习如何自制emoji&#xff0c;学习内容主要分为3个方面&#xff0c;分3次来讲&#xff0c;根本在于了解了turtle的使用&#xff01; 1.完成一个爱心应援牌 2.完成静态的emoji 3.让emoji动起来&#xff01; 今天我们来学习第一个部分。 文章目录…

推荐一个图像生成开源项目——Fooocus

目录 什么是Fooocus&#xff1f; 项目地址 性能消耗 如何安装 效果对比 总结 什么是Fooocus&#xff1f; Fooocus是一款图像生成软件&#xff0c;但它不同寻常&#xff0c;是对稳定扩散&#xff08;Stable Diffusion&#xff09;和Midjourney的设计理念的巧妙重新思考。本…

C语言经典100例题(42)--学习使用auto定义变量的用法

目录 题目 问题分析 代码 运行结果 题目 学习使用auto定义变量的用法 问题分析 auto存储类型只对属于块的变量有效。auto变量具有自动存储期限、块作用域&#xff0c;并且无连接。auto存储类型几乎从来不用明确地指明&#xff0c;因为对于在块内部声明的变量&#xff0c;…

超经典 Linux 运维巡检脚本及示例

inux 系统日常巡检脚本&#xff0c;巡检内容包含了&#xff1a;磁盘、内存、CPU、进程、文件更改、用户登录等一系列的操作&#xff0c;直接用就行了。 报告以邮件发送到邮箱&#xff0c;在 log 下生成巡检报告。 一、巡检脚本 #!/bin/bash # Author: HanWei # Date: 2020-…

Nginx__高级进阶篇之LNMP动态网站环境部署

动态网站和LNMP&#xff08;LinuxNginxMySQLPHP&#xff09;都是用于建立和运行 web 应用程序的技术。 动态网站是通过服务器端脚本语言&#xff08;如 PHP、Python、Ruby等&#xff09;动态生成网页内容的网站。通过这种方式&#xff0c;动态网站可以根据用户的不同请求生成不…

Sentinel-限流降级

0.目录 初识Sentinel 流量控制 隔离和降级 授权规则 规则持久化 1.初识Sentinel 1.0目录 雪崩问题及解决方案 服务保护技术对比 Sentinel介绍和安装 微服务整合Sentinel 1.1 雪崩问题 1.1.1 引起雪崩的原本 如果服务D出现了问题&#xff0c;那么当服务A调用服务D时&…

Jetpack Compose 1.5 发布:全新 Modifier 系统带来性能大幅提升

不久前 Compose 1.5.0 稳定版发布&#xff0c;在组合的性能方面得到明显改善&#xff0c;这主要归功于对 Modifier API 的持续重构。 Modifier 是 Compose 中的重要概念&#xff0c;为 Composition 中的 LayoutNode 配置各种样式信息以用于后续渲染。在 1.3.0 之前的 Modifier …

【教师节特辑】做个教师节快乐照片墙吧

写作原因&#xff1a; 教师节到了&#xff0c;身边或多或少都有很多不少的老师&#xff0c;基本以前认识的老师都不记得了&#xff0c;以后总也会认识一些日本老师的。程序员&#xff0c;就应该以自己的方式来庆祝教师节。想了下&#xff0c;要不还是做个照片墙把。 项目链接 …

2024年java面试--mysql(2)

系列文章目录 2024年java面试&#xff08;一&#xff09;–spring篇2024年java面试&#xff08;二&#xff09;–spring篇2024年java面试&#xff08;三&#xff09;–spring篇2024年java面试&#xff08;四&#xff09;–spring篇2024年java面试–集合篇2024年java面试–redi…

电商API与电商数据经济的产生【电商平台-淘宝/京东/拼多多下的API数据经济】

计算机连接了互联网后&#xff0c;释放出了巨大的创新力和价值&#xff0c;同样地&#xff0c;智能合约一旦连接到快速增长的链下数据和API经济&#xff0c;也将变得无比强大。如果智能合约可以连接至链下数据提供商、web API、企业系统、云服务商、物联网设备、支付系统以及其…

高分三号1米分辨率飞机检测识别数据集

二、背景介绍 合成孔径雷达(Synthetic Aperture Radar, SAR) 是一种主动式的微波成像系统&#xff0c;它不受光照、云雾 和气候等自然条件影响&#xff0c;具备全天时、全天候对地 观测的能力&#xff0c;已成为遥感领域重要的信息获取平 台。近年来&#xff0c;随着遥感成像技…

Redis主从复制集群的介绍及搭建

在现代的软件开发中&#xff0c;数据的可靠性和可用性是至关重要的。Redis&#xff0c;作为一个开源的、内存中的数据结构存储系统&#xff0c;以其出色的性能和灵活的数据结构&#xff0c;赢得了开发者们的广泛喜爱。而 Redis 的主从复制功能&#xff0c;更是为我们提供了一种…

基于AHP模型指标权重分析python整理

一 背景介绍 日常会有很多定量分析的场景&#xff0c;然而也会有一些定性分析的场景针对定性分析的场景&#xff0c;预测者只能通过主观判断分析能力来推断事物的性质和发展趋势然而针对个人的直觉和虽然能够有一定的协助判断效果&#xff0c;但是很难量化到指标做后期的复用 …

Mybatis学习笔记2 增删改查及核心配置文件详解

Mybatis学习笔记1 Mybatis入门_biubiubiu0706的博客-CSDN博客 将Mybatis进行封装 SqlSessionUtil工具类 package com.example.util;import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFacto…

modinfo对比内核版本号

加载内核&#xff0c;出现版本不一样 cat /proc/verison查看内核板本 模块版本&#xff1a;显示模块的版本号。 $ modinfo [OPTIONS] [MODULE] 参数说明-F, --field <field>: 指定要显示的字段&#xff0c;可以使用逗号分隔多个字段。-k, --kernel <kernel>: 指定…

第15章_瑞萨MCU零基础入门系列教程之Common I2C总线模块

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

香橙派使用外设驱动库wiringOP来驱动蜂鸣器

硬件接线 回顾香橙派的物理引脚对应&#xff1a; 所以将VCC接到1&#xff0c;GND接到6&#xff0c;I/O口接到7&#xff1a; 代码编写 香橙派的wiringOP库提供了很多的例程&#xff0c;可以将blink.c拷贝进自己的代码文件夹来修改&#xff1a; 小插曲---将手动对齐的Tab和自动对…