IPv6レディのサンプルソース

#include    <stdio.h>
#include    <ctype.h>
#include    <unistd.h>
#include    <stdlib.h>
#include    <string.h>
#include    <errno.h>
#include    <signal.h>
#include    <poll.h>
#include    <sys/param.h>
#include    <sys/types.h>
#include    <sys/socket.h>
#include    <netinet/in.h>
#include    <arpa/inet.h>
#include    <netdb.h>
#include    <sys/wait.h>

/* サーバソケット:シグナルハンドラ用にグローバルに */
#define MAXSOCK 64
int     Soc[MAXSOCK];
int     SocMax=0;

/* プロトタイプ宣言 */
int SetSignal();
int ReadParam();
int ServerSocketNew(char *portnm,int soc[],int maxsock);
int AcceptLoop(int soc[],int smax);


int main(int argc,char *argv[])
{
char    *port;
int     i;

        /* 引数の解釈 */
        if(argc<2){
                fprintf(stderr,"no port\n");
                fprintf(stderr,"server port\n");
                return(-1);
        }
        else{
                port=argv[1];
                fprintf(stderr,"port=%s\n",port);
        }

        /* パラメーターファイルの読み込み */
        if(ReadParam()==-1){
                fprintf(stderr,"ReadParam():-1\n");
                return(-1);
        }

        /* シグナルハンドラのセット */
        SetSignal();

        /* サーバソケットの準備 */
        if((SocMax=ServerSocketNew(port,Soc,MAXSOCK))==-1){
                fprintf(stderr,"ServerSocketNew(%s):-1\n",port);
                return(-1);
        }

        /* アクセプト・ループ */
        if(AcceptLoop(Soc,SocMax)==-1){
                fprintf(stderr,"AcceptLoop:-1\n");
                for(i=0;i<SocMax;i++){
                        close(Soc[i]);
                }
                return(-1);
        }

        /* サーバソケットのクローズ */
        for(i=0;i<SocMax;i++){
                close(Soc[i]);
        }

        /* 正常終了 */
        return(0);
}

/* シグナルハンドラのセット */
int SetSignal()
{
        return(0);
}

/* パラメータファイルの読み込み */
int ReadParam()
{
        return(0);
}

int ServerSocketNew(char *portnm,int soc[],int maxsock)
{
struct addrinfo hints,*res,*res0;
int     error;
int     smax;
int     sockmax;
char    hbuf[NI_MAXHOST],sbuf[NI_MAXSERV];
#ifdef  IPV6_V6ONLY
const int       on=1;
#endif

        memset(&hints,0,sizeof(hints));
        hints.ai_socktype=SOCK_STREAM;
        hints.ai_flags=AI_PASSIVE;
        error=getaddrinfo(NULL,portnm,&hints,&res0);
        if(error){
                fprintf(stderr,"ServerSocketNew:%s:%s\n",portnm,gai_strerror(error));
                return(-1);
        }

        smax=0;
        sockmax=-1;
        for(res=res0;res&&smax<maxsock;res=res->ai_next){
                soc[smax]=socket(res->ai_family,res->ai_socktype,res->ai_protocol);
                if(soc[smax]<0){
                        continue;
                }
#ifdef  IPV6_V6ONLY
                if(res->ai_family==AF_INET6){
                        (void)setsockopt(soc[smax],IPPROTO_IPV6,IPV6_V6ONLY,&on,sizeof(on));
                }
#endif
                if(bind(soc[smax],res->ai_addr,res->ai_addrlen)<0){
                        close(soc[smax]);
                        soc[smax]=-1;
                        continue;
                }
                if(listen(soc[smax],5)<0){
                        close(soc[smax]);
                        soc[smax]=-1;
                        continue;
                }
                error=getnameinfo(res->ai_addr,res->ai_addrlen,hbuf,sizeof(hbuf),sbuf,sizeof(sbuf),NI_NUMERICHOST|NI_NUMERICSERV);
                if(error){
                        fprintf(stderr,"ServerSocketNew:%s\n",gai_strerror(error));
                        freeaddrinfo(res0);
                        return(-1);
                }
                fprintf(stderr,"ServerSocketNew:listen to %s %s\n",hbuf,sbuf);
                if(soc[smax]>sockmax){
                        sockmax=soc[smax];
                }
                smax++;
        }

        freeaddrinfo(res0);

        if(smax==0){
                fprintf(stderr,"ServerSocketNew:no socket to listen to\n");
                return(-1);
        }

        return(smax);
}


/* アクセプト・ループ */
int AcceptLoop(int soc[],int smax)
{
int     ret;
int     acc;
struct pollfd   targets[MAXSOCK];
int     end;
int     nready;
struct sockaddr_storage from;
socklen_t       fromlen;
int     i;
char    hbuf[NI_MAXHOST],sbuf[NI_MAXSERV];
int     error;

        ret=0;

        for(i=0;i<smax;i++){
                targets[i].fd=soc[i];
                targets[i].events=POLLIN|POLLERR;
        }

        do{
                end=0;
                switch((nready=poll(targets,smax,-1))){
                        case    -1:
                                if(errno!=EINTR){
                                        perror("poll");
                                        ret=-1;
                                        end=1;
                                }
                                break;
                        case    0:
                                fprintf(stderr,"timeout\n");
                                break;
                        default:
                                for(i=0;i<smax;i++){
                                        if(targets[i].revents&(POLLIN|POLLERR)){
                                                fromlen=sizeof(from);
                                                /* 接続受付 */
                                                acc=accept(soc[i],(struct sockaddr *)&from,&fromlen);
                                                if(acc<0){
                                                        continue;
                                                }
                                                error=getnameinfo((struct sockaddr *)&from,fromlen,hbuf,sizeof(hbuf),sbuf,sizeof(sbuf),NI_NUMERICHOST|NI_NUMERICSERV);
                                                if(error){
                                                        fprintf(stderr,"getnameinfo:error\n");
                                                }
                                                else{
                                                        fprintf(stderr,"accept (%d) from %s %s\n",i,hbuf,sbuf);
                                                }

                                                /* 送受信ループ */

                                                /* アクセプトソケットクローズ */
                                                close(acc);
                                        }
                                }
                                break;
                }
        }while(end!=1);

        return(ret);
}

 


フレームページへ

from 2007/1/13