设为首页 加入收藏

TOP

IO的多路复用和信号驱动(一)
2015-07-26 13:14:24 来源: 作者: 【 】 浏览:77
Tags:复用 信号 驱动

Linux为多路复用IO提供了较多的接口,有select(),pselect(),poll()的方式,继承自BSD和System V 两大派系。


  select模型比较简单,“轮询”检测fd_set的状态,然后再采取相应的措施。


  信号驱动模型有必要仔细研究一下,一般有如下步骤:


  具体进下文client例程。


  写了一个聊天程序的demo,把这两种技术都使用了。服务端采取多路复用的IO方式,代替多进(线)程的模型,客服端采取的是信号驱动,如下:


容易产生bug的地方都写注释里边了。


serv.c


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


void endServ(int sig)
{
? ? printf("Server ended!\n");
? ? exit(-1);
}


int main()
{
? ? // signal
? ? struct sigaction act;
? ? sigemptyset(&act.sa_mask);
? ? act.sa_handler = endServ;
? ? act.sa_flags = 0;
? ? sigaction(SIGINT,&act,0);
? ? printf("This server is started,enter CTRL+C to end. \n");


? ? int servfd = socket(AF_INET,SOCK_STREAM,0);
? ? if(servfd == -1) {
? ? ? ? printf("something wrong with socket():%m\n");
? ? ? ? exit(-1);
? ? }


? ? struct sockaddr_in addr;
? ? addr.sin_family = AF_INET;
? ? addr.sin_port = htons(9999);
? ? inet_pton(AF_INET,"127.0.0.1",&addr.sin_addr);


? ? if (bind(servfd,(struct sockaddr*)&addr,sizeof(addr)) == -1) {
? ? ? ? printf("Some thing wrong with bind():%m\n");
? ? ? ? exit(-1);
? ? }
? ? printf("Bind success!\n");


? ? listen(servfd,20);
? ?
? ? int numbers=0;//how many clients has accepted
? ? fd_set fs;
? ? FD_ZERO(&fs);
? ? int client_fd[100];
? ? int i;
? ? for(i=0;i<100;++i)
? ? {
? ? ? ? client_fd[i] = -1;
? ? }


? ? int maxfd=0;
? ? char buf[1024];
? ? for(;;)
? ? {
? ? ? ? maxfd =0;
? ? ? ? FD_ZERO(&fs);
? ? ? ? FD_SET(servfd,&fs);
? ? ? ? maxfd = maxfd>servfd?maxfd:servfd;
? ? ? ? for(i=0;i? ? ? ? {
? ? ? ? ? ? if(client_fd[i] != -1) {
? ? ? ? ? ? ? ? FD_SET(client_fd[i],&fs);
? ? ? ? ? ? ? ? maxfd = maxfd>client_fd[i]?maxfd:client_fd[i];
? ? ? ? ? ? }
? ? ? ? }


? ? ? ? int res = select(maxfd+1,&fs,0,0,0);
? ? ? ? if(res == -1) {
? ? ? ? ? ? printf("Something wrong with select():%m\n");
? ? ? ? ? ? exit(-1);
? ? ? ? }


? ? ? ? if(FD_ISSET(servfd,&fs) && numbers < 100) {
? ? ? ? ? ? printf("New client!\n");
? ? ? ? ? ? client_fd[numbers] = accept(servfd,0,0);
? ? ? ? ? ? numbers++;
? ? ? ? }
? ? ? ?
? ? ? ? for(i=0;i? ? ? ? {
? ? ? ? ? ? bzero(buf,sizeof(buf));
? ? ? ? ? ? //judge if client_fd[i] equal -1 is necessary
? ? ? ? ? ? //if a client quited,next time the program will
? ? ? ? ? ? //have a segment default
? ? ? ? ? ? //also it should be in the front.
? ? ? ? ? ? if(client_fd[i] != -1 && FD_ISSET(client_fd[i],&fs))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? res = recv(client_fd[i],buf,sizeof(buf),0);
? ? ? ? ? ? ? ? if(res == 0) {
? ? ? ? ? ? ? ? ? ? printf("A client quit\n");
? ? ? ? ? ? ? ? ? ? close(client_fd[i]);
? ? ? ? ? ? ? ? ? ? FD_CLR(client_fd[i],&fs);
? ? ? ? ? ? ? ? ? ? client_fd[i] = -1;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else if(res == -1) {
? ? ? ? ? ? ? ? ? ? printf("Something wrong with net.\n");
? ? ? ? ? ? ? ? ? ? exit(-1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else {
? ? ? ? ? ? ? ? ? ? int j;
? ? ? ? ? ? ? ? ? ? for(j=0;j? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? if(client_fd[j] != -1)
? ? ? ? ? ? ? ? ? ? ? ? ? ? send(client_fd[j],buf,sizeof(buf),0);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
}


client:


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


static int fd;


void show(int sig)
{
? ? char buf[1024] = {0};
? ? int n = read(fd,buf,sizeof(buf));
? ? buf[n] = 0;
? ? write(1,"MSG:",strlen("MSG:"));
? ? write(1,buf,strlen(buf));
}


int main()
{
? ? struct sigaction act;
? ? sigemptyset(&act.sa_mask);
? ? act.sa_handler = show;
? ? //This is necessary,in last loop read() counld be interrupt;
? ? act.sa_flags = SA_RESTART;
? ? sigaction(SIGIO,&act,0);


? ? fd = socket(AF_INET,SOCK_STREAM,0);
? ? if(fd == -1) {
? ? ? ? printf("Cannot get socketfd!:%m\n");
? ? ? ? exit(-1);
? ? }


? ? struct sockaddr_in addr;
? ? addr.sin_family = AF_INET;
? ? addr.sin_port = htons(9999);
? ? inet_pton(AF_IN

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android程序员不可错过的十款实用.. 下一篇免费工具检测Hacking Team间谍软件

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: