linux客户端服务端模型,使用select模型的服务器

程序简介:这是一个运用select函数进行IO复用的服务器模型。它的原理是:当一个客户端连接上服务器时,服务器就将其连接的fd加入fd_set集合,等到这个连接准备好读或写的时候,就通知程序进行IO操作,与客户端进行数据通信。它是一个经典的IO复用模型,但当同时连接的客户端数量变大时,fd_set集合就变得很大,而每次要时行IO操作时,都要遍历一次这个集合,导致效率降低,所以它现在基本上被EPOLL模型代替了。

上代码:

#include "my_unp.h"

int main(void)

{

int i, maxi, maxfd, listenfd, connfd, sockfd;

pid_t childpid;

int nready, client[FD_SETSIZE];

ssize_t n;

fd_set rset, allset;

char buf[MAXLINE];

socklen_t clilen;

struct sockaddr_in cliaddr, servaddr;

//创建用于TCP协议的套接字

listenfd = Socket(AF_INET, SOCK_STREAM, 0);

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(SERV_PORT);

//把socket和socket地址结构联系起来

Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));

//开始监听LISTENQ端口

Listen(listenfd, LISTENQ);

maxfd = listenfd;

maxi = -1;

//初始化结构fd_set

for(i=0; i

client[i] = -1;

FD_ZERO(&allset);

FD_SET(listenfd, &allset);

while(1)

{

rset = allset;

//阻塞程序,等待某个事件的发生(见注解1)

//这里没有对Select函数设置超时,会导致程序有安全隐患

nready = Select(maxfd+1, &rset, NULL, NULL, NULL);

//如果监听的套接字变得可读,就建立一个新链接

if( FD_ISSET(listenfd, &rset) )

{

clilen = sizeof(cliaddr);

//调用accept函数并更新相关的数据结构

connfd = Accept(listenfd, (SA*)&cliaddr, &clilen);

//输出客户端的IP地址与端口号,还有处理(子)进程的PID

printf("connection from %s, port %d. process with clild %d\n",

Inet_ntop(AF_INET, (void*)&cliaddr.sin_addr, buff, sizeof(buff)),

ntohs(cliaddr.sin_port), childpid);

for(i=0; i

{

if( client[i] < 0 )

{

client[i] = connfd;

break;

}

}

//链接数已经达到上限了

if( FD_SETSIZE == i )

error_quit("too many clients");

//增加新的描述符到集合中

FD_SET(connfd, &allset);

if( connfd > maxfd )

maxfd = connfd;

if( i > maxi )

maxi = i;

//利用select的返回值来检查末就绪的描述符

if( --nready <= 0 )

continue;

}

//扫描每个现在客户链接

for(i=0; i<=maxi; i++)

{

sockfd = client[i];

if( sockfd < 0 )

continue;

if( FD_ISSET(sockfd, &rset) )

{

n = Read(sockfd, buf, MAXLINE);

//如果客户关闭了链接,就更新数据结构

if( 0 == n )

{

Close(sockfd);

FD_CLR(sockfd, &allset);

client[i] = -1;

}

//否则,就回射一段字符给客户端

else

Writen(sockfd, buf, n);

}

if( --nready <= 0 )

break;

}

}

return 0;

}

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值