信号駆動式IOに基づくリスニングソケット(O_ASYNC,O_NONBLOCK)

3133 ワード

背景
Source: http://blog.csdn.net/ordeder/article/details/22733077
(Unixネットワークプログラミングボリューム1の説明は以下の通り)ソケット信号駆動式io(SIGIO)を設定するには3つのステップが必要である.
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#
",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...
",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...
",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...#