背景
Source: http://blog.csdn.net/ordeder/article/details/22733077
(Unix网络编程卷1说明如下)
设置套接字信号驱动式io(SIGIO)需要三个步骤:1.建立SIGIO信号的处理函数
2.设置套接字的属主,即fcntl:F_SETOWN
3.开启套接字的信号驱动是IO,即:fcntl:O_ASYNC
引起套接字产生SIGIO信号的情况有:
1监听套接字上有连接请求已完成
-----------------------
2断连请求已发起
3断连请求已完成
4连接的一半已经关闭
----------------------
5数据到达套接字
6数据从套接字发出
7发生异步错误
小结
由1可得,监听套接字适合异步信号IO;
2-7可得异步IO不适合TCP连接套接字;
5-7可得,UDP适合异步信号IO
监听套接字的异步信号IO
server.c
- #include<fcntl.h>
- #include<signal.h>
- ...
- int listenfd,connfd;
- void sig_iohander(int signo)
- {
- int rn;
- char buff[128];
- puts("get sigio...");
- connfd = accept(listenfd,NULL,0);
- if(connfd == -1){perror("accept");return;}
- rn = recv(connfd,buff,127,0);
- if(rn == -1) {perror("recv");return;}
- buff[rn]='\0';
- printf("recv #%s#\n",buff);
- close(connfd);
- }
- int main(int argc,char*argv[])
- {
- struct sockaddr_in cliaddr,servaddr;
- int queuelen=5,i,flag;
- pid_t cpid[WORKERSIZE];
- listenfd = socket(AF_INET,SOCK_STREAM,0);
- signal(SIGIO,sig_iohander);
- flag = fcntl(listenfd,F_GETFL,0);
- flag |= O_NONBLOCK | O_ASYNC;
- fcntl(listenfd,F_SETFL,flag);//将监听套接字设置为非阻塞(非阻塞是因为listenfd发生的连接可能在调用accept的时候,对方已近关闭连接了,这时候如果监听套接字为阻塞,那么进程将长期阻塞直到有新连接完成),异步IO(O_ASYNC)
- fcntl(listenfd,F_SETOWN,getpid()); //设定listenfd上接收到的中断
- 信号的处理进程ID
- bzero(&servaddr,sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(2989);
- bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
- listen(listenfd,queuelen);
- while(scanf("%d",&i))//故意让程序阻塞于命令行io,实则等待SIGIO
- 的骚扰~
- puts("jump out of scanf block...");
- return 0;
- }
client.c
- ...
- sockfd = socket(AF_INET,SOCK_STREAM,0);
- rc = connect(sockfd,(struct sockaddr*)&servaddr,sizeof
- (servaddr));
- if(rc == -1)
- {
- perror("connect error");
- exit(0);
- }
- printf("pid#%d connected...\n",getpid());
- char content[128];
- sprintf(content,"client pid=%d say hello...",getpid());
- send(sockfd,content,strlen(content),0);
- shutdown(sockfd,SHUT_WR);
- int rn;
- while((rn == recv(sockfd,content,127,0)))//rn == 0 : 表示服务端
- 关闭了写(FIN),即解释为EOF
- {
- content[rn] = '\0';
- puts(content);
- }
- printf("pid#%d done...\n",getpid());
- ...
测试结果:
服务端如下显示:
get sigio...
recv #client pid=2236 say hello...#
get sigio...
recv #client pid=2237 say hello...#
get sigio...
recv #client pid=2238 say hello...#
get sigio...
recv #client pid=2239 say hello...#
get sigio...
recv #client pid=2240 say hello...#
get sigio...
recv #client pid=2241 say hello...#
get sigio...
recv #client pid=2242 say hello...#
recv #client pid=2236 say hello...#
get sigio...
recv #client pid=2237 say hello...#
get sigio...
recv #client pid=2238 say hello...#
get sigio...
recv #client pid=2239 say hello...#
get sigio...
recv #client pid=2240 say hello...#
get sigio...
recv #client pid=2241 say hello...#
get sigio...
recv #client pid=2242 say hello...#