北京加密机现场select问题

问题描述

北京项目通过调用我们提供的库libsigxt.a与加密机通信,c/s架构,客户端启用多个线程,每个线程流程有以下三步,连接加密机,签名,关闭链接。在正常运行一段时间后会出现不能连接加密机服务问题。

连接服务器代码如下:

setnonblocking(sk_fd);

ret = connect(sk_fd, (struct sockaddr *)&sa_serv, server_len);
    P_DEBUG("main connect ret:%d\n",ret);
    if(ret < 0){
        if(errno != EINPROGRESS){
            P_DEBUG("mainip connect error ret.\n");
        }else{
            tv.tv_sec = timeout;
            tv.tv_usec = 0;
            fd_set wset;
            FD_ZERO(&wset);
            FD_SET(sk_fd,&wset);
            ret = select(sk_fd+1,NULL,&wset,NULL,&tv);
            printf("main select ret is %d\n",ret);
            if(ret<0){
                P_DEBUG("mainip select error,can not connect to server.\n");
            }else if(ret == 0){
                P_DEBUG("mainip connect timeout.\n");
            }else{
                if(FD_ISSET(sk_fd,&wset)){
                    P_DEBUG("mainip connect successful.\n");
                    setblocking(sk_fd);
                }else{
                    P_DEBUG("not fd_isset(). not connected.\n");
                    goto quit;
                }    
            }
        }
    }

先设置非阻塞模式,然后通过connect连接,当返回0时,表示连接成功;当返回-1,并且errno 为 EINPROGRESS表示正在连接过程中,通过select监听wset,当select返回小于0时,表示连接失败;当select返回0时,表示超时;当返回大于0时,表示连接成功,重新再设置成阻塞模式。

根据现场日志打印,当select返回非1的正数,则监听不到可写事件,连接失败,发送数据也失败。

原因查找定位

通过网上搜索发现,1024限定的不只是监听的个数,还是文件描述符的最大值。FD_SETSIZE限制了文件描述符的个数。
但是根据fd_set存储文件描述符的原理,FD_SETSIZE限制的应该是文件描述符的最大值,当然限制了最大值也就限制了个数。

下面一段摘自man select中的原话
"Executing FD_CLR() or FD_SET() with a value of fd that is negative or is equal to  or larger than FD_SETSIZE will result in undefined behavior."

再查下现场打开的描述符个数,的确大于1024,造成select返回的结果不可预期。

解决方案

既然select使用除了问题,那就换成epoll来监听,修改代码如下:

setnonblocking(sk_fd);

        ret = connect(sk_fd, (struct sockaddr *)&sa_serv, server_len);
        if(ret == 0){
            goto connect_success;
        }
        
        if(ret<0 && errno != EINPROGRESS){
            P_DEBUG("back connect failed.\n");
            goto connect_failure;    
        }

        if((epfd = epoll_create(1))<0){
            P_DEBUG("main epoll create error.\n");
            goto connect_failure;
        }
        memset(&ev, 0, sizeof ev);
        ev.events = EPOLLOUT;
        ev.data.fd = sk_fd;

        if(epoll_ctl(epfd, EPOLL_CTL_ADD, sk_fd, &ev)<0){
            P_DEBUG("main epoll_ctl error.\n");
            goto connect_failure;
        }
        
        n = epoll_wait(epfd,events,1,itimeout);
        P_DEBUG("back epoll_wait n is %d\n",n);
        if(n<=0 || events[0].events & EPOLLERR){
            P_DEBUG("back connect failure.\n");
            goto connect_failure;
        }
     

connect_success:
    
    P_DEBUG("connect success.\n");
    setblocking(sk_fd);

   ......

connect_failure:
    if(sk_fd>0)
        close(sk_fd);
    sk_fd = -1;
    if(epfd>0)
        close(epfd);
    return -1;

}

经测试发现,没有再出现连接失败问题。

结论:建议linux下弃用select。

       
   

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

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

相关文章

处理SIGCHLD信号

在上一讲中&#xff0c;我们使用fork函数得到了一个简单的并发服务器。然而&#xff0c;这样的程序有一个问题&#xff0c;就是当子进程终止时&#xff0c;会向父进程发送一个SIGCHLD信号&#xff0c;父进程默认忽略&#xff0c;导致子进程变成一个僵尸进程。僵尸进程一定要处理…

nginx源码阅读(一).综述

前言 nginx作为一款开源的轻量级高性能web服务器,是非常值得立志从事服务端开发方向的人学习的。现今nginx的最新版本是nginx-1.13.6,代码量也日渐庞大,但是由于其核心思想并没改变,为了降低阅读难度,我选择的是nginx-1.0.15版本,并且由于时间和水平有限,重点关注的是nginx的启…

系统级性能分析工具perf的介绍与使用

系统级性能优化通常包括两个阶段&#xff1a;性能剖析&#xff08;performance profiling&#xff09;和代码优化。 性能剖析的目标是寻找性能瓶颈&#xff0c;查找引发性能问题的原因及热点代码。 代码优化的目标是针对具体性能问题而优化代码或编译选项&#xff0c;以改善软…

C/C++内存问题检查利器——Purify

C&#xff0f;C内存问题检查利器——Purify 一、 引言 我们都知道软件的测试&#xff08;在以产品为主的软件公司中叫做QA—Quality Assessment&#xff09;占了整个软件工程的30% -50%&#xff0c;但有这么一种说法&#xff0c;即使是最优秀测试专家设计出来的测试…

浅析三种特殊进程:孤儿进程,僵尸进程和守护进程

其实有时想想linux内核的设计也蕴含着很多人生哲学,在linux中有这么几个特殊进程中,我们一开始见到它们的名字可能还会觉得很诧异,但在了解完了原理后,我们仔细想想,这样的命名也不无道理!下面我就给大家分别介绍一下这三种特殊的进程! 1.孤儿进程 如果父进程先退出,子进程还没…

差生文具多之(二): perf

栈回溯和符号解析是使用 perf 的两大阻力&#xff0c;本文以应用程序 fio 的观测为例子&#xff0c;提供一些处理它们的经验法则&#xff0c;希望帮助大家无痛使用 perf。 前言 系统级性能优化通常包括两个阶段&#xff1a;性能剖析和代码优化&#xff1a; 性能剖析的目标是寻…

Linux下的I/O复用与epoll详解(ET与LT)

前言 I/O多路复用有很多种实现。在linux上&#xff0c;2.4内核前主要是select和poll&#xff0c;自Linux 2.6内核正式引入epoll以来&#xff0c;epoll已经成为了目前实现高性能网络服务器的必备技术。尽管他们的使用方法不尽相同&#xff0c;但是本质上却没有什么区别。本文将重…

彻底学会使用epoll(一)——ET模式实现分析

注&#xff1a;之前写过两篇关于epoll实现的文章&#xff0c;但是感觉懂得了实现原理并不一定会使用&#xff0c;所以又决定写这一系列文章&#xff0c;希望能够对epoll有比较清楚的认识。是请大家转载务必注明出处&#xff0c;算是对我劳动成果的一点点尊重吧。另外&#xff0…

sys/queue.h分析(图片复制不过来,查看原文)

这两天有兴趣学习使用了下系统头文件sys/queue.h中的链表/队列的实现&#xff0c;感觉实现的很是优美&#xff0c;关键是以后再也不需要自己实现这些基本的数据结构了&#xff0c;哈哈&#xff01; 我的系统环境是 正好需要使用队列&#xff0c;那么本篇就以其中的尾队列&…

线程池原理及C语言实现线程池

备注&#xff1a;该线程池源码参考自传直播客培训视频配套资料&#xff1b; 源码&#xff1a;https://pan.baidu.com/s/1zWuoE3q0KT5TUjmPKTb1lw 密码&#xff1a;pp42 引言&#xff1a;线程池是一种多线程处理形式&#xff0c;大多用于高并发服务器上&#xff0c;它能合理有效…

iptables 的mangle表

mangle表的主要功能是根据规则修改数据包的一些标志位&#xff0c;以便其他规则或程序可以利用这种标志对数据包进行过滤或策略路由。 内网的客户机通过Linux主机连入Internet&#xff0c;而Linux主机与Internet连接时有两条线路&#xff0c;它们的网关如图所示。现要求对内网进…

Linux之静态库

命名规则&#xff1a; lib 库的名字 .a 制作步骤 生成对应.o文件 .c .o 将生成的.o文件打包 ar rcs 静态库的名字&#xff08;libMytest.a&#xff09; 生成的所有的.o 发布和使用静态库&#xff1a; 1&#xff09; 发布静态 2&#xff09; 头文件 文件如下图所示&…

Linux之动态库

命令规则 lib 名字 .so 制作步骤 1&#xff09;生成与位置无关的代码&#xff08;生成与位置无关的代码&#xff09; 2&#xff09;将.o打包成共享库&#xff08;动态库&#xff09; 发布和使用共享库 动态库运行原理&#xff1a; 生成动态库&#xff1a; gcc -fPIC -c *.c -…

linux下源码安装vsftpd-3.0.2

1&#xff09;在http://vsftpd.beasts.org/网站中查找并下载 vsftpd-3.0.2.tar.gz源码包 2)如果自己的机器上安装有yum可以用yum grouplist | less指令查看以下开发环境&#xff0c;当然这一步不做也行 3&#xff09;拆解源码包 4&#xff09;查看源码包 5&#xff09;编辑…

Gdb 调试core文件详解

一&#xff0c;什么是coredump 我们经常听到大家说到程序core掉了&#xff0c;需要定位解决&#xff0c;这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止&#xff0c;并且在满足一定条件下&#xff08;这里为什么说需要满足一定的条件呢&#…

Windows下编译openssl库

1、概述 OpenSSL是一个开放源代码的软件库包&#xff0c;它实现了 SSL&#xff08;Secure SocketLayer&#xff09;和 TLS&#xff08;Transport Layer Security&#xff09;协议&#xff0c;所以应用程序可以使用这个包来进行安全通信&#xff0c;避免窃听&#xff0c;同时确…

windows环境下C语言socket编程

最近由于实验需要&#xff0c;要求写一个c程序与java程序通信的软件&#xff0c;为了测试首先写了一个windows环境下c语言的socket&#xff08;tcp&#xff09;通信程序。 首先socket通信的步骤&#xff1a; 图一 socket通信步骤&#xff08;转载) 图二 三次握手协议&…

Makefile(三)

在平时使用中&#xff0c;可以使用以下的makefile来编译单独的代码 src $(wildcard *.c) obj $(patsubst %.c, %.o, $(src))CC gcc CFLAGS -Wall -gall:$(target)$(target):%:%.c$(CC) $< -o $ $(CFLAGS).PHONY: clean all clean:-rm -rf $(target) 使用方法就是make 后…

数据类型(C++)

不同系统会有不同差异&#xff1a; 类型 位(byte) 范围 char 1 -128—127 or 0 – 255 unsigned char 1 0 – 255 signed int 1 -128—127 int 4 -2^31 – 2^32-1 unsigned int 4 0 – 2^32 signed int 4 -2^31 – 2^32-1 short int 2 2^15 – 2^15-1 …

dup2函数

将当前系统中的进程信息打印到文件中 命令行&#xff1a;ps aux > out 将ps得到的信息重定向到out文件中 使用dup2文件在程序中完成。 int dup2(int oldfd,int newfd); /*** dup2.c ***/ #include<stdio.h> #include<fcntl.h> #include<unistd.h> #includ…