服务器之select
select
- select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开的文件描述符个数并不能改变select监听文件个数
- 解决1024以下客户端时使用select是很合适的,但如果链接客户端过多,select采用的是轮询模型,会大大降低服务器响应效率,不应在select上投入更多精
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout); nfds: 监控的文件描述符集里最大文件描述符加1,因为此参数会告诉内核检测前多少个文件描述符的状态
readfds: 监控有读数据到达文件描述符集合,传入传出参数
writefds: 监控写数据到达文件描述符集合,传入传出参数
exceptfds: 监控异常发生达文件描述符集合,如带外数据到达异常,传入传出参数
timeout: 定时阻塞监控时间,3种情况
.NULL,永远等下去
.设置timeval,等待固定时间
.设置timeval里时间均为0,检查描述字后立即返回,轮询
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
void FD_CLR(int fd, fd_set *set); //把文件描述符集合里fd清0
int FD_ISSET(int fd, fd_set *set); //测试文件描述符集合里fd是否置1
void FD_SET(int fd, fd_set *set); //把文件描述符集合里fd位置1
void FD_ZERO(fd_set *set); //把文件描述符集合里所有位清0
server
/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "wrap.h" #define MAXLINE 80
#define SERV_PORT 6666 int main(int argc, char *argv[])
{
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, client[FD_SETSIZE]; /* FD_SETSIZE 默认为 1024 */
ssize_t n;
fd_set rset, allset;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN]; /* #define INET_ADDRSTRLEN 16 */
socklen_t cliaddr_len;
struct sockaddr_in cliaddr, servaddr; listenfd = Socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT); Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); Listen(listenfd, ); /* 默认最大128 */ maxfd = listenfd; /* 初始化 */
maxi = -; /* client[]的下标 */ for (i = ; i < FD_SETSIZE; i++)
client[i] = -; /* 用-1初始化client[] */ FD_ZERO(&allset);
FD_SET(listenfd, &allset); /* 构造select监控文件描述符集 */ for ( ; ; ) {
rset = allset; /* 每次循环时都从新设置select监控信号集 */
nready = select(maxfd+, &rset, NULL, NULL, NULL); if (nready < )
perr_exit("select error");
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
cliaddr_len = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
for (i = ; i < FD_SETSIZE; i++) {
if (client[i] < ) {
client[i] = connfd; /* 保存accept返回的文件描述符到client[]里 */
break;
}
}
/* 达到select能监控的文件个数上限 1024 */
if (i == FD_SETSIZE) {
fputs("too many clients\n", stderr);
exit();
} FD_SET(connfd, &allset); /* 添加一个新的文件描述符到监控信号集里 */
if (connfd > maxfd)
maxfd = connfd; /* select第一个参数需要 */
if (i > maxi)
maxi = i; /* 更新client[]最大下标值 */ if (--nready == )
continue; /* 如果没有更多的就绪文件描述符继续回到上面select阻塞监听,
负责处理未处理完的就绪文件描述符 */
}
for (i = ; i <= maxi; i++) { /* 检测哪个clients 有数据就绪 */
if ( (sockfd = client[i]) < )
continue;
if (FD_ISSET(sockfd, &rset)) {
if ( (n = Read(sockfd, buf, MAXLINE)) == ) {
Close(sockfd); /* 当client关闭链接时,服务器端也关闭对应链接 */
FD_CLR(sockfd, &allset); /* 解除select监控此文件描述符 */
client[i] = -;
} else {
int j;
for (j = ; j < n; j++)
buf[j] = toupper(buf[j]);
Write(sockfd, buf, n);
}
if (--nready == )
break;
}
}
}
close(listenfd);
return ;
}
client
/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h" #define MAXLINE 80
#define SERV_PORT 6666 int main(int argc, char *argv[])
{
struct sockaddr_in servaddr;
char buf[MAXLINE];
int sockfd, n; sockfd = Socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT); Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); while (fgets(buf, MAXLINE, stdin) != NULL) {
Write(sockfd, buf, strlen(buf));
n = Read(sockfd, buf, MAXLINE);
if (n == )
printf("the other side has been closed.\n");
else
Write(STDOUT_FILENO, buf, n);
}
Close(sockfd);
return ;
}
包含了”wrap.c”和“wrap.h”文件在上两篇博客中,这里就不重复给出了
服务器之select的更多相关文章
- linux下维护服务器之常用命令
linux下维护服务器之常用命令! 第1套如下: 正则表达式: 1.如何不要文件中的空白行和注释语句: [root@localhost ~]# grep -v '^$' 文件名 |grep -v '^ ...
- Web服务器之iis,apache,tomcat三者之间的比较
IIS-Apache-Tomcat的区别 IIS与Tomcat的区别 IIS是微软公司的Web服务器.主要支持ASP语言环境. Tomcat是Java Servlet 2.2和JavaServer P ...
- linux服务器之LVS、Nginx和HAProxy负载均衡器对比
linux服务器之LVS.Nginx和HAProxy负载均衡器对比. LVS特点: 1.抗负载能力强,使用IP负载均衡技术,只做分发,所以LVS本身并没有多少流量产生: 2.稳定性.可靠性好,自身 ...
- 【转】Android 服务器之SFTP服务器上传下载功能
原文网址:http://blog.csdn.net/tanghua0809/article/details/47056327 本文主要是讲解Android服务器之SFTP服务器的上传下载功能,也是对之 ...
- 搭建VPN服务器之PPTP
搭建VPN服务器之PPTP 1. 查看系统是否支持PPP 一般自己的系统支持,VPS需要验证. [root@oldboyedu ~]# cat /dev/ppp cat: /dev/ppp: No s ...
- backup服务器之rsync服务
backup服务器之rsync服务 rsync是开源的.快速的.多功能的可实现全量及增量的本地或远程数据同步备份的优秀工具.它拥有scp.cp的全量复制功能,同时比scp.cp命令更优秀.更强大. ...
- 【转】Android 服务器之SFTP服务器上传下载功能 -- 不错
原文网址:http://blog.csdn.net/tanghua0809/article/details/47056327 本文主要是讲解Android服务器之SFTP服务器的上传下载功能,也是对之 ...
- Session服务器之Memcached与Redis
安装Memcached[root@nginx ~]# yum -y install libevent memcached 指定用户大小等信息,工作环境中常指定大小一般为4到8G,此信息测试使用.[ro ...
- Session服务器之Redis
Session服务器之Redis Redis与Memcached的区别内存利用率:使用简单的key value (键值对)存储的话,Mermcached 的内存利用率更高,而如果Redis采用hash ...
随机推荐
- 表单送件前的Check(二) (未完)
#region 新增表单前的Check动作 public static void NewFormRequestCheck(string _FormID, string _VocaEmpID, stri ...
- SQL 多并发 多人取号,防止重复取号SQL 办法
BEGIN TRAN SELECT * from 表明 WITH(HOLDLOCK) UPDATE 表名 SET 值=1 WHERE 字段=@carrierNo; ...
- 关于Git无法提交 index.lock的解决办法
今天提交代码时,在一次提交,莫名其妙没成功后,再次用git commit -a命令时,出现以下错误,无论是用git还是TortoiseGit都会出现以下这个问题.. $ git commit -a f ...
- VBA Exit Do语句
当想要根据特定标准退出Do循环时,可使用Exit Do语句. 它可以同时用于Do...While和Do...Until直到循环. 当Exit Do被执行时,控制器在Do循环之后立即跳转到下一个语句. ...
- 【转载】C#使用as关键字将对象转换为指定类型
在C#的编程开发过程中,很多时候涉及到数据类型的转换,可使用强制转换的方式,不过强制转换数据类型有时候会抛出程序异常错误,可以使用as关键字来进行类型的转换,如果转换成功将返回转换后的对象,如果转换不 ...
- 上传图片,图片过大压缩处理以及解决自拍时会出现图片横屏的bug修复、长按保存图片
js部分:module.exports = { resize: function (file, callback, options) { //配置 options = Object.assign({ ...
- html5细线表格制作
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- http接口测试工具-Advanced-REST-client
非常好用的http接口测试工具 相信作为一个java开发人员,大家或多或少的要写或者接触一些http接口.而当我们需要本地调试接口常常会因为没有一款好用的工具而烦恼.今天要给大家介绍一款非常好用.实用 ...
- GlusterFS分布式存储系统
一,分布式文件系统理论基础 1.1 分布式文件系统出现 计算机通过文件系统管理,存储数据,而现在数据信息爆炸的时代中人们可以获取的数据成指数倍的增长,单纯通过增加硬盘个数来扩展计算机文件系统的存储容量 ...
- visual studio调试exe程序
标题:How to debug and profile any EXE with Visual Studio 文章:https://devblogs.microsoft.com/visualstudi ...