select限制之文件描述符限制
1、一个进能够打开的最大文件描述符限制。可以通过两种方式修改
ulimit -n :获取最大文件描述符个数
ulimit -n 2048:修改为2048个
该限制的测试代码:
客户端程序:
/*
1、select受最大文件描述符限制。测试程序如下
2、select的fd_set集合容量的限制(FD_SIZE),在头文件中限制。
*/
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<signal.h>
#include <sys/time.h> #include <sys/resource.h>
#define ERR_EXIT(m)\
do\
{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0);
//为何要使用sleep来推迟ERR_EXIT(). 客户端除去 0 、1、2描述符,创建了1021个描述符。在创建1022个套接字时,失败了,失败之后进程退出,发送许多FIN给服务器端。服务器端已完成连接队列中维护了1021个条目。正好有FIN之后,可以空出套接字处理第1021个条目。如果延迟客户端的退出服务器端就只有1020个了。
int main(void)
{
int count=0;
while(1)
{ int sock;
if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
{
sleep(5);//推迟客户端的close(便于准确查看服务器端到底能接受多少连接).按理说服务器端只能接受1020个,但是中间有客户端口关闭使得服务端口能够重复利用,使得服务器端也能使用1021个描述符(0,1,2,3(监听套接口)),如果不推迟,创建第1022个套接口时,客户端退出进程,前面的1021个套接口要发送FIN,close和accept交替
ERR_EXIT("socket");
}
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(5188);
servaddr.sin_addr.s_addr=inet_addr("127.0.0.1"); if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
ERR_EXIT("connect");//创建第1022个套接字失败。 0,1,2已经打开。 1024个
struct sockaddr_in localaddr;
socklen_t addrlen=sizeof(localaddr);
if(getsockname(sock,(struct sockaddr *)&localaddr,&addrlen)<0)
ERR_EXIT("getsockname");
printf("ip=%s port=%d\n",inet_ntoa(localaddr.sin_addr),ntohs(localaddr.sin_port));
printf("count=%d\n",++count);
}
return 0; }
服务器端程序:
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<signal.h>
#include<sys/wait.h>
#define ERR_EXIT(m)\
do\
{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0)
ssize_t readn(int fd,void *buf,size_t count)
{
size_t nleft=count;
ssize_t nread;
char *bufp=(char*)buf;
while(nleft>0)
{
if((nread=read(fd,bufp,nleft))<0)
{
if(errno==EINTR)
continue;
else
return -1;
}
else if(nread==0)
return (count-nleft);
bufp+=nread;
nleft-=nread;
}
return count;
}
ssize_t writen(int fd, const void *buf, size_t count)
{
size_t nleft=count;
ssize_t nwritten;
char *bufp=(char*)buf;
while(nleft>0)
{
if((nwritten=write(fd,bufp,nleft))<=0)
{
if(errno==EINTR)
continue;
return -1;
}else if(nwritten==0)
continue;
bufp+=nwritten;
nleft-=nwritten;
}
return count; }
ssize_t recv_peek(int sockfd,void *buf,size_t len)
{
while(1)
{
int ret=recv(sockfd,buf,len,MSG_PEEK);//从sockfd读取内容到buf,但不去清空sockfd,偷窥
if(ret==-1&&errno==EINTR)
continue;
return ret;
}
}
//偷窥方案实现readline避免一次读取一个字符
ssize_t readline(int sockfd,void * buf,size_t maxline)
{
int ret;
int nread;
size_t nleft=maxline;
char *bufp=(char*)buf;
while(1)
{
ret=recv_peek(sockfd,bufp,nleft);//不清除sockfd,只是窥看
if(ret<0)
return ret;
else if(ret==0)
return ret;
nread=ret;
int i;
for(i=0;i<nread;i++)
{
if(bufp[i]=='\n')
{
ret=readn(sockfd,bufp,i+1);//读出sockfd中的一行并且清空
if(ret!=i+1)
exit(EXIT_FAILURE);
return ret;
}
}
if(nread>nleft)
exit(EXIT_FAILURE);
nleft-=nread;
ret=readn(sockfd,bufp,nread);
if(ret!=nread)
exit(EXIT_FAILURE);
bufp+=nread;//移动指针继续窥看
}
return -1;
}
void handle_sigchld(int sig)
{ while(waitpid(-1,NULL, WNOHANG)>0)
; }
void handle_sigpipe(int sig)
{
printf("recevie a sig=%d\n",sig);//打印,不退出服务器进程
}
int main(void)
{
int count=0;//测试描述符限制
signal(SIGCHLD,handle_sigchld);
signal(SIGPIPE,handle_sigpipe);
int listenfd;
if((listenfd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
ERR_EXIT("socket error");
//本地协议地址赋给一个套接字
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(5188);
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);//表示本机地址 //开启地址重复使用,关闭服务器再打开不用等待TIME_WAIT
int on=1;
if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0)
ERR_EXIT("setsockopt error");
//绑定本地套接字
if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
ERR_EXIT("bind error");
if(listen(listenfd,SOMAXCONN)<0)//设置监听套接字(被动套接字)
ERR_EXIT("listen error"); struct sockaddr_in peeraddr;//对方套接字地址
socklen_t peerlen=sizeof(peeraddr); int client[FD_SETSIZE];//select最大文件描述符,用来保存已连接文件描述符。
int i=0;
for(i=0;i<FD_SETSIZE;i++)
{
client[i]=-1;
}
int conn;//已连接套接字(主动套接字)
int nready;
int maxi=0;//最大不空闲位置
int maxfd=listenfd;
fd_set rset,allset;
FD_ZERO(&rset);
FD_ZERO(&allset);
FD_SET(listenfd,&allset);
while(1)
{
rset=allset;
nready=select(maxfd+1,&rset,NULL,NULL,NULL);//如果是监听套接口(服务器),已完成连接队列不为空时,accept不再阻塞;
if(nready==-1)
{
if(errno==EINTR)
continue;
ERR_EXIT("select error");
}
if(nready==0)
continue;
if(FD_ISSET(listenfd,&rset))//监听口有事件,已完成队列不为空
{
conn=accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen);
if(conn==-1)
ERR_EXIT("accept error");
for(i=0;i<FD_SETSIZE;i++)
{
if(client[i]<0)
{
client[i]=conn;
if(i>maxi)
maxi=i;//更新最大不空闲位置
break;
} }
if(i==FD_SETSIZE)
{
fprintf(stderr,"too many clents\n");
exit(EXIT_FAILURE);
}
printf("ip=%s port=%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); printf("%d\n",++count);//服务器端口应该是1020. 0,1,2和监听的套接口用掉四个 //select的fd_set集合容量的限制
FD_SET(conn,&allset);//将已连接套接字描述符放入allset,用于监测已连接套接口是否有客户端数据到来
if(conn>maxfd)
maxfd=conn;//更新maxfd
if(--nready<=0)
continue;//如果事件已经处理完,就继续循环监听,不再执行以下代码 }
for(i=0;i<=maxi;i++)//小于等于
{
conn=client[i];
if(conn==-1)
continue;
//已经连接套接字是否有事件,不用while(1)循环处理客户端发送,有select监听。
if(FD_ISSET(conn,&rset))
{
int ret;
char recvbuf[1024];
memset(&recvbuf,0,sizeof(recvbuf));
ret=readline(conn,recvbuf,1024);
if(ret==-1)
ERR_EXIT("readline");
else if(ret==0)
{
printf("client close\n");
FD_CLR(conn,&allset);//客户端清理,select就不用去监听
client[i]=-1;
close(conn);//前面程序BUG,对方关闭之后,我们服务器也要关闭套接口。让客户端接收到通知
}
fputs(recvbuf,stdout);
writen(conn,recvbuf,strlen(recvbuf));//write :aaa bbb ,RST,写aaa接收bbb,再bbb,有了SIGPIPE
if(--nready==0)
continue;
}
}
}
return 0;
}
select限制之文件描述符限制的更多相关文章
- 关于信号打断正在读取终端的read与select来监视0文件描述符的问题
首先说一下对于这个问题外的一些话: 我觉得我们应该有种质疑的态度,因为接下来的这个问题就和我们平常所想的不一样. 介绍一下问题: 曾经一直听说信号可以打断一个正在阻塞的进程,但是今天我试了一下关于信号 ...
- Linux下利用文件描述符恢复的成功失败实验
1.测试环境准备[oracle@redhat3 ~]$ uname -aLinux redhat3 2.6.32-573.el6.x86_64 #1 SMP Wed Jul 1 18:23:37 ED ...
- 误删除innodb ibdata数据文件 文件句柄 文件描述符 proc fd
误删除innodb ibdata数据文件 文件句柄 文件描述符 proc fd http://www.cnblogs.com/gomysql/p/3702216.html 提示:如果不小心通过 ...
- 文件描述符、文件表项指针、inode节点的关系
内核使用3种数据结构表示打开的文件,他们之间的关系决定了在文件共享方面一个进程对另一个进程的影响. (1) 每个进程在进程表中都有一个纪录项,纪录项中包含一张打开文件描述符表,每个文件描述符各占一项, ...
- Linux内核笔记--深入理解文件描述符
内核版本:linux-2.6.11 文件描述符(file descriptor)在Linux编程里随处可见,设备读写.网络通信.进程通信,fd可谓是关键中的关键. 深入理解可以增加我们使用它的信心. ...
- Linux 利用进程打开的文件描述符(/proc)恢复被误删文件
Linux 利用进程打开的文件描述符(/proc)恢复被误删文件 在 windows 上删除文件时,如果文件还在使用中,会提示一个错误:但是在 linux 上删除文件时,无论文件是否在使用中,甚至是还 ...
- Linux 文件描述符和重定向
200 ? "200px" : this.width)!important;} --> 介绍 文件描述符是与文件输入.输出相关联的整数,在编写脚本时会经常使用标准的文件描述符 ...
- linux专题一之文件描述符、重定向、管道符、tee命令
本节讨论一下几个问题: 1. 文件描述符. 2. 重定向. 3. 管道符 4. tee的用法. 1. 文件描述符. 在linux系统中一切皆文件.文件夹和设备都是文件.如何用来区别不同的文件呢?这里的 ...
- CentOS最大文件描述符限制更改
系统级的限制:/proc/sys/fs/file-max中设定了系统最大能打开的文件数. 查看该值可以用如下方式: [root@#panda ~]# cat /proc/sys/fs/file-max ...
随机推荐
- spring cloud 实现基于Nacos权重的负载均衡
package com.water.step.service.user.nacos; import com.alibaba.nacos.api.exception.NacosException; im ...
- Jenkins+pytest+Allure搭建自动化测试
持续集成(CONTINUOUS INTEGRATION) 在CI环境中,开发人员将会频繁地向主干提交代码.这些新提交的代码在最终合并到主干前,需要经过编译和自动化测试流进行验证. 持续交付(CONTI ...
- 网络编程—【自己动手】用C语言写一个基于服务器和客户端(TCP)!
如果想要自己写一个服务器和客户端,我们需要掌握一定的网络编程技术,个人认为,网络编程中最关键的就是这个东西--socket(套接字). socket(套接字):简单来讲,socket就是用于描述IP地 ...
- go 结构体初始化
package main import "fmt" type Dog struct { Name string } func TestStruct() { // 方式1 //var ...
- Helium文档12-WebUI自动化-go_to在当前的Web浏览器窗口中打开指定的URL
前言 go_to在当前的Web浏览器窗口中打开指定的URL 入参介绍 url def go_to(url): """ :param url: URL to open. : ...
- 技术实操丨HBase 2.X版本的元数据修复及一种数据迁移方式
摘要:分享一个HBase集群恢复的方法. 背景 在HBase 1.x中,经常会遇到元数据不一致的情况,这个时候使用HBCK的命令,可以快速修复元数据,让集群恢复正常. 另外HBase数据迁移时,大家经 ...
- etc/river.toml
# MySQL address, user and password # user must have replication privilege in MySQL. my_addr = " ...
- 输出c字母图形
1 #include "stdio.h" 2 #include "math.h" 3 int main(void) 4 { 5 double y; 6 int ...
- Graph-GCN
前言 在大型图中,节点的低维向量embedding被证明了作为各种各样的预测和图分析任务的特征输入是非常有用的.顶点embedding最基本的基本思想是使用降维技术从高维信息中提炼一个顶点的邻居信息, ...
- 《JavaScript高级程序设计》——第二章在HTML使用JavaScript
这章讲的是JavaScript在HTML中的使用,也就是<script>元素的属性.书中详细讲了async.defer.src和type四个<script>的属性. 下面是对第 ...