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