服务器开发——setsockopt函数

news/2024/9/19 3:39:37/文章来源:https://www.cnblogs.com/xvxing/p/18290355

setsockopt()

setsockopt() 是一个用于设置套接字选项的 Unix 系统调用。它允许程序员修改套接字的行为,以适应不同的网络环境和应用程序需求。

1. 函数介绍

函数原型:

#include <sys/socket.h>  
/*** level:选项所在的协议层。例如,SOL_SOCKET 表示套接字层,IPPROTO_TCP 或 IPPROTO_IP 表示 TCP 或 IP 层。* optname:要设置的选项的名称。每个协议层都定义了自己的一组选项。* optval:指向一个变量的指针,该变量包含选项的新值。这个变量的类型取决于 optname 的值。* @return 成功(0);失败(-1)
*/
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

使用实例:

int opt = 1;  
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {  perror("setsockopt(SO_REUSEADDR)");  // 错误处理  
}

2.常见参数介绍

2.1 SO_REUSEADDR

1. 介绍TIME_WAIT

四次挥手:
在这里插入图片描述

当服务器和客户端建立连接以后,如果服务器关闭了客户端的连接,服务器处于TIME_WAIT状态。此时关闭服务器,再次开启服务器会发现bind()函数调用失败。
也就是,服务器关闭后短时间内无法再次打开。

2. 测试代码

1.服务器端:

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>#define SERV_PORT 9000int main(int argc,char** argv)
{int listenfd = socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in serv_addr;memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);int ret=0;int opt = 1;//setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));ret = bind(listenfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));if(ret==-1){printf("bind()函数调用失败\n");return -1;}ret = listen(listenfd,32);if(ret==-1){printf("listen()函数调用失败\n");return -1;}int connfd;const char* pcontent = "I sent sth to client!";for(;;){printf("服务器进入等待状态!\n");connfd = accept(listenfd,(struct sockaddr*)NULL,NULL);int n = write(connfd,pcontent,strlen(pcontent));printf("数据写入成功,connfd=%d,写入数据量为%d\n",connfd,n);close(connfd);}close(listenfd);return 0;
}

在这里插入图片描述

2.客户端:


#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>#define SERV_PORT 9000    //要连接到的服务器端口,服务器必须在这个端口上listen着int main(int argc, char *const *argv)
{    //这些演示代码的写法都是固定套路,一般都这么写int sockfd = socket(AF_INET, SOCK_STREAM, 0); //创建客户端的socket,大家可以暂时不用管这里的参数是什么,知道这个函数大概做什么就行struct sockaddr_in serv_addr; memset(&serv_addr,0,sizeof(serv_addr));//设置要连接到的服务器的信息serv_addr.sin_family = AF_INET;                //选择协议族为IPV4serv_addr.sin_port = htons(SERV_PORT);         //连接到的服务器端口,服务器监听这个地址if(inet_pton(AF_INET,"192.168.0.126",&serv_addr.sin_addr)<=0){printf("调用inet_pton()失败,退出!\n");exit(-1);}if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0){printf("调用connect()失败,退出!\n");exit(-1);}printf("client开始读取数据!\n");int n;char recvline[1000+1];while(( n = read(sockfd,recvline,1000)) > 0){printf("读取的数据数目为%d\n",n);recvline[n]=0;printf("收到的内容为:%s\n",recvline);}close(sockfd);printf("程序执行完毕,退出!\n");return 0;
}

在这里插入图片描述

2.2 SO_REUSEPORT

1.多进程端口复用

在多进程开发中,我们可以使用多个进程监听同一个IP:PORT,由操作系统分配传入的数据包,充分利用多核CPU,从而提高了整体的系统性能和吞吐量。

2.代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>void create_and_listen(int port) {int listen_fd;struct sockaddr_in addr;listen_fd = socket(AF_INET, SOCK_STREAM, 0);if (listen_fd < 0) {perror("socket");exit(EXIT_FAILURE);}// 没有设置 SO_REUSEPORT  选项/*int opt = 1;if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEPORT , &opt, sizeof(opt)) < 0) {perror("setsockopt");exit(EXIT_FAILURE);}*/memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(port);if (bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {perror("bind");close(listen_fd);exit(EXIT_FAILURE);}if (listen(listen_fd, SOMAXCONN) < 0) {perror("listen");close(listen_fd);exit(EXIT_FAILURE);}printf("Listening on port %d\n", port);while (1) {int conn_fd = accept(listen_fd, NULL, NULL);if (conn_fd < 0) {perror("accept");close(listen_fd);exit(EXIT_FAILURE);}// 处理连接的代码close(conn_fd);}close(listen_fd);
}int main() {int port = 5000;for (int i = 0; i < 4; i++) {pid_t pid = fork();if (pid < 0) {perror("fork");exit(EXIT_FAILURE);} else if (pid == 0) {// 子进程create_and_listen(port);exit(0);}}// 父进程等待子进程退出while (wait(NULL) > 0);return 0;
}

没有开启SO_REUSEPORT 的时候:
在这里插入图片描述
只有一个进程可以绑定到这个套接字。


开启后:
在这里插入图片描述
有多个进程可以绑定到这个套接字。

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

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

相关文章

Python OpenCv对规则物体进行实时检测

很多情况需要对物体进行检测,常规的方法也有很多种。但是检测出来的边缘一般都是非常多,结果也是非常杂乱的,显然这种结果不是我们想要的。如果颜色相较于背景非常鲜艳的可以调节hsv阈值再进行检测,如果是一直在运动的物体可以通过帧差法进行物体检测,还有很多高深的算法也…

学习canvas(一些常用api)

当然,以下是这些常用Canvas API的总结,按照Markdown格式编写: 常用Canvas API总结 1. 获取绘图上下文 const canvas = document.getElementById(myCanvas); const ctx = canvas.getContext(2d); // 或 webgl2. 绘制矩形 ctx.fillStyle = blue; ctx.fillRect(10, 10, 150, 10…

uniapp 解决本地跨域问题

让每一滴智慧绘制成一条不归路!

UniVAE:基于Transformer的单模型、多尺度的VAE模型

大家都知道,Transformer的$\mathscr{O}(n^2)$复杂度是它的“硬伤”之一。不过凡事有弊亦有利,$\mathscr{O}(n^2)$的复杂度也为Transformer带来很大的折腾空间,我们可以灵活地定制不同的attention mask,来设计出不同用途的Transformer模型来,比如UniLM、K-BERT等。 本文介绍…

从变分编码、信息瓶颈到正态分布:论遗忘的重要性

这是一篇“散文”,我们来谈一下有着千丝万缕联系的三个东西:变分自编码器、信息瓶颈、正态分布。 众所周知,变分自编码器是一个很经典的生成模型,但实际上它有着超越生成模型的含义;而对于信息瓶颈,大家也许相对陌生一些,然而事实上信息瓶颈在去年也热闹了一阵子;至于正…

应用升级

本文是在你已经安装三个软件的基础上进行优化 一、卸载NFG Multi Crack软件(没有就不用管) 二、进入Lsposed软件 点击模块,可以看到已安装的两个模块1. 点击FL-Xposed,勾选以下应用,然后返回2. 点击HookVip,勾选Fakelocation,然后返回三、进入隐藏应用列表软件 1. 点击模…

哪些方法可以将word导出为pdf格式?

在日常工作和学习中,我们经常需要将Word文档转换为PDF格式,以便更好地保存、分享和打印文件。PDF格式具有跨平台兼容性好、不易被篡改等优点,因此得到了广泛应用。那么Word如何转PDF呢?本文将介绍三种实用的word转pdf的方法,帮助读者轻松实现文档格式的转换。 方法一:使用…

2024春秋杯 stdout

考点:文件,setvbuf缓冲区,ret2syscall,ret2csu 题目给了libc文件。 main函数和vlun函数存在明显的栈溢出 int __cdecl main(int argc, const char **argv, const char **envp) {char buf[80]; // [rsp+0h] [rbp-50h] BYREFinit(argc, argv, envp);puts("where is my s…

怎么看时序图

时序图看法 从上到下,从左到右 看一个单位时间,拆分成一个一个模块 简单的时序图,一根线串口通信SPIS时序图总体传输24个bit注意无效电平可能传输不同的电平

工程仪器振弦采集仪的设计与研发进展

工程仪器振弦采集仪的设计与研发进展 工程仪器振弦采集仪是一种用于测量和记录物体振动参数的仪器。它能够实时采集物体的振动信号,并通过内部的传感器将振动信号转化为电信号,然后进行信号放大和处理,最终以数字形式显示或存储。 河北稳控科技振弦采集仪的设计与研发进展主…

近似排序......

一年没动算法的蒻蒟随手点开了之前做过的一道【近似排序】,然后开始了,恢复之旅......TFLSOJ【近似排序】 看到题目经简单分析后先写出了一种傻瓜解法,(可能叫 暴力??) #include<bits/stdc++.h> using namespace std; int x,y; int a[110]; int main(){cin>&g…

SMU Summer 2024 Contest Round 1

SMU Summer 2024 Contest Round 1 Dice and Coin 题意 给个 n 面骰子和一枚硬币,初始投骰子,若骰子的值在 1 到 \(K-1\) 之间则反复投硬币,硬币为正则该值翻倍,否则为 0 ,当值为 0 输掉游戏或者大于等于 \(K\) 时赢得游戏结束,问你可以赢得游戏的概率为多少。 思路 以 1 …