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

news/2025/2/16 3:02:15/

目录

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 socketudp_sock = socket(PF_INET, SOCK_DGRAM, 0); // create udp socketprintf("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 0void 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.ppmy.cn/news/1096064.html

相关文章

vue3+ts+vite项目引入echarts,vue3项目echarts组件封装

概述 技术栈&#xff1a;Vue3 Ts Vite Echarts 简介&#xff1a; 图文详解&#xff0c;教你如何在Vue3项目中引入Echarts&#xff0c;封装Echarts组件&#xff0c;并实现常用Echarts图例 文章目录 概述一、先看效果1.1 静态效果1.2 动态效果 二、话不多数&#xff0c;引入 …

Ubuntu之apt-get系列--安装JDK8--方法/教程

原文网址&#xff1a;Ubuntu之apt-get系列--安装JDK8--方法/教程_IT利刃出鞘的博客 简介 本文介绍如何在Ubuntu下安装JDK8。 验证是否安装 可以通过如下命令判断系统是否有安装ssh服务&#xff1a; 命令 java -version 结果 如上所示&#xff0c;表示还没有安装。 查看…

Java HashMap常见面试题

1、HashMap 是什么&#xff1f;它的特点是什么&#xff1f; HashMap 是 Java 集合框架中的一个实现类&#xff0c;它基于哈希表实现。HashMap 具有以下特点&#xff1a; 键值对存储&#xff1a;数据以键值对的形式存储&#xff0c;每个键都是唯一的。快速查找&#xff1a;通过…

离线安装docker-compose

系统环境 系统是centos7.6 离线安装docker 下载docker 下载地址&#xff1a;https://download.docker.com/linux/static/stable/x86_64/ docker-20.10.21.tgz安装docker tar -xvf docker-20.10.21.tgz cp docker/* /usr/bin 离线安装docker-compose 下载docker-compose 普…

前端的规范

假如团队中的小伙伴在提交代码时没有遵循规范要求&#xff0c;只写了一个"fix"或"update&#xff0c;这会给其他小伙伴造成困扰&#xff0c;不得不花时间查看代码和推测逻辑。 不仅会浪费了时间和精力&#xff0c;可能会导致项目以下问题&#xff1a; 可读性差…

伦敦金的走势高低的规律

伦敦金市场是一个流动性很强的市场&#xff0c;其价格走势会在诸多因素的影响下&#xff0c;出现反复的上下波动&#xff0c;如果投资者能够在这些高低走势中找到一定的规律&#xff0c;在相对有利的时机入场和离场&#xff0c;就能够通过不断的交易&#xff0c;累积大量的财富…

2023/09/07 c++qt day2

#include <iostream>using namespace std; //封装一个学生类 struct stu { private://存放学生的成绩int stu_score[256];//记录学生个数int stu_num; public://用于设置学生个数void setNum(){cout<<"请输入学生的个数"<<" ";cin>&g…

2023年9月北京/广州/深圳DAMA-CDGP数据治理专家认证报名

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…