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