select_tut

Autres langues

Langue: ja

Version: 2006-05-13 (openSuse - 09/10/07)

Section: 2 (Appels système)

̾Á°

select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - Ʊ´ü I/O ¤Î¿½Å²½

½ñ¼°


/* POSIX.1-2001 ¤Ë½¾¤¦¾ì¹ç */


#include <sys/select.h> /* °ÊÁ°¤Îµ¬³Ê¤Ë½¾¤¦¾ì¹ç */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set); #define _XOPEN_SOURCE 600 #include <sys/select.h> int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);

ÀâÌÀ

select() (¤ä pselect()) ¤Ï¡¢Æ±»þ¤ËÊ£¿ô¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿ (¤ä¥½¥±¥Ã¥È¥Ï¥ó¥É¥ë) ¤ò¸úΨŪ¤Ë°·¤ª¤¦¤È¤¹¤ë C ¥×¥í¥°¥é¥à¤Ç¡¢ÍפȤʤë´Ø¿ô¤Ç¤¢¤ë¡£ ¤³¤Î´Ø¿ô¤Î¼çÍפʰú¤­¿ô¤Ï¡¢3¼ïÎà¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ÎÇÛÎó readfds, writefds, exceptfds ¤Ç¤¢¤ë¡£ select() ¤ÎÄ̾ï¤Î»È¤ï¤ìÊý¤Ï¡¢¤Ò¤È¤Ä¤Þ¤¿¤ÏÊ£¿ô¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Î ¡Ö¾õÂÖ¤ÎÊѲ½¡×¤òÂԤäƤ¤¤ë´Ö¡¢Ää»ß (block) ¤¹¤ë¤³¤È¤Ç¤¢¤ë¡£ ¡Ö¾õÂÖ¤ÎÊѲ½¡×¤È¤Ï¡¢°Ê²¼¤Î¤¤¤º¤ì¤«¤Î¾ì¹ç¤Ç¤¢¤ë: (1) ¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤«¤é¼èÆÀ¤Ç¤­¤ëʸ»ú¤¬Áý¤¨¤¿¾ì¹ç¡¢ (2) ¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Ë½ñ¤­¹þ¤à¤¿¤á¤Î ¥«¡¼¥Í¥ë¤ÎÆâÉô¥Ð¥Ã¥Õ¥¡Æâ¤Ë»ÈÍѤǤ­¤ë¶õ´Ö¤¬¤Ç¤­¤¿¾ì¹ç¡¢ (3) ¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤¬¥¨¥é¡¼¤Ë¤Ê¤Ã¤¿¾ì¹ç (¥½¥±¥Ã¥È¤ä¥Ñ¥¤¥×¤Î¾ì¹ç¤Ï¡¢¤³¤ì¤ÏÀܳ¤Î¾ü¤¬¥¯¥í¡¼¥º¤µ¤ì¤¿¾ì¹ç)¡£

Í×Ì󤹤ë¤È¡¢ select() ¤ÏÊ£¿ô¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Î´Æ»ë¤ò¹Ô¤¦¤À¤±¤Î¤â¤Î¤Ç¡¢ ¤½¤ì¤ò¹Ô¤¦¤¿¤á¤Îɸ½àŪ¤Ê Unix ¥³¡¼¥ë¤Ç¤¢¤ë¡£

¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ÎÇÛÎó¤Ï ¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿½¸¹ç (file descriptor set) ¤È¸Æ¤Ð¤ì¤ë¡£³Æ¡¹¤Î½¸¹ç¤Ï fd_set ¤È¤·¤ÆÀë¸À¤µ¤ì¡¢¤½¤ÎÆâÍÆ¤Ï FD_CLR(), FD_ISSET(), FD_SET(), FD_ZERO() ¤È¤¤¤Ã¤¿¥Þ¥¯¥í¤Ë¤è¤Ã¤ÆÊѹ¹¤Ç¤­¤ë¡£ ¿·¤·¤¤¥Ç¥£¥¹¥¯¥ê¥×¥¿½¸¹ç¤ËÂФ·¤Æ¤Ï¡¢Ä̾ï FD_ZERO() ¤òºÇ½é¤Ë»È¤¦¡£ ¤½¤Î¸å¤Ç¡¢´Æ»ëÂоݤȤ·¤¿¤¤¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ò°ì¤Ä°ì¤Ä FD_SET() ¤ÇÄɲ乤롣 select() ¤Ï¤³¤ì¤é¤Î½¸¹ç¤ÎÆâÍƤò¡¢°Ê¹ß¤Ë½Ò¤Ù¤ëµ¬Â§¤Ë½¾¤Ã¤Æ½¤Àµ¤¹¤ë¡£ select() ¤ò¸Æ¤ó¤À¸å¡¢¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤¬¤Þ¤À½¸¹ç¤Ë¸ºß¤·¤Æ¤¤¤ë¤«¤É¤¦¤«¤Ï¡¢ FD_ISSET() ¥Þ¥¯¥í¤Ë¤è¤Ã¤ÆÄ´¤Ù¤ë¤³¤È¤¬¤Ç¤­¤ë¡£ FD_ISSET() ¤Ï¤½¤Î¥Ç¥£¥¹¥¯¥ê¥×¥¿¤¬½¸¹ç¤Ë¸ºß¤·¤Æ¤¤¤ì¤Ð 0 °Ê³°¤ÎÃͤòÊÖ¤·¡¢ ¸ºß¤·¤Æ¤¤¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤¹¡£ FD_CLR() ¤Ï½¸¹ç¤«¤é¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Îºï½ü¤ò¹Ô¤¦¡£

°ú¤­¿ô

readfds
¤³¤Î½¸¹ç¤Ë´Þ¤Þ¤ì¤ë¤¤¤º¤ì¤«¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Ç ¥Ç¡¼¥¿¤ÎÆɤ߹þ¤ß¤¬²Äǽ¤Ë¤Ê¤Ã¤¿¤«¤É¤¦¤«¤ò´Æ»ë¤¹¤ë¡£ select() ¤«¤éÌá¤ë»þ¤Ë¡¢readfds ¤Î¤¦¤Á¡¢ recv(2) (¥½¥±¥Ã¥È¤Î¾ì¹ç) ¤ä read(2) (¥Ñ¥¤¥×¡¢¥Õ¥¡¥¤¥ë¡¢¥½¥±¥Ã¥È¤Î¾ì¹ç) ¤Ë¤è¤Ã¤Æľ¤Á¤ËÆɤ߹þ¤ß²Äǽ¤Ê¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿°Ê³°¤Ï ½¸¹ç¤«¤éºï½ü¤µ¤ì¤ë¡£
writefds
¤³¤Î½¸¹ç¤Ë´Þ¤Þ¤ì¤ë¤¤¤º¤ì¤«¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Ç ¥Ç¡¼¥¿¤ò½ñ¤­¹þ¤à¥¹¥Ú¡¼¥¹¤¬¤¢¤ë¤«¤É¤¦¤«¤ò´Æ»ë¤¹¤ë¡£ select() ¤«¤éÌá¤ë»þ¤Ë¡¢writefds ¤Î¤¦¤Á¡¢ send(2) (¥½¥±¥Ã¥È¤Î¾ì¹ç) ¤ä write(2) (¥Ñ¥¤¥×¡¢¥Õ¥¡¥¤¥ë¡¢¥½¥±¥Ã¥È¤Î¾ì¹ç) ¤Ë¤è¤Ã¤Æľ¤Á¤Ë½ñ¤­¹þ¤ß²Äǽ¤Ê¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿°Ê³°¤Ï ½¸¹ç¤«¤éºï½ü¤µ¤ì¤ë¡£
exceptfds
¤³¤Î½¸¹ç¤Ë´Þ¤Þ¤ì¤ë¤¤¤º¤ì¤«¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Ç Îã³°¤ä¥¨¥é¡¼¤¬À¸¤¸¤Æ¤¤¤ë¤«¤É¤¦¤«¤ò´Æ»ë¤¹¤ë¡£ ¤·¤«¤·¡¢¤³¤ì¤Ï¤¿¤À¤Î±½¤Ë²á¤®¤º¡¢ ¼ÂºÝ¤Ë exceptfds ¤Ç´Æ»ë¤·¤Æ¤¤¤ë¤â¤Î¤Ï ÂÓ°è³° (out-of-band: OOB) ¥Ç¡¼¥¿¤Ê¤Î¤À¡£ OOB ¥Ç¡¼¥¿¤Ï¥½¥±¥Ã¥È¤Ç MSG_OOB ¥Õ¥é¥°¤òÍѤ¤¤ë¤ÈÁ÷¿®¤µ¤ì¤ë¡£ ½¾¤Ã¤Æ¡¢¼ÂºÝ¤Ë¤Ï exceptfds ¤Ï¥½¥±¥Ã¥È¤Ë¤·¤«Å¬ÍѤǤ­¤Ê¤¤¡£ ¤³¤Î¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï recv(2) ¤È send(2) ¤ò¸«¤è¡£ select() ¤«¤éÌá¤ë»þ¤Ë¡¢exceptfds ¤Î¤¦¤Á¡¢ OOB ¥Ç¡¼¥¿¤ÎÆɤ߹þ¤ß¤¬²Äǽ¤Ë¤Ê¤Ã¤Æ¤¤¤ë¥Ç¥£¥¹¥¯¥ê¥×¥¿°Ê³°¤Ï ½¸¹ç¤«¤éºï½ü¤µ¤ì¤ë¡£ OOB ¥Ç¡¼¥¿¤ÎÆɤ߹þ¤ß (recv(2) ¤Ç¹Ô¤¦) ¤Ï 1 ¥Ð¥¤¥È¤À¤±¤·¤«¤Ç¤­¤Ê¤¤¤¬¡¢ OOB ¥Ç¡¼¥¿¤Î½ñ¤­¹þ¤ß (send(2) ¤Ç¹Ô¤¦) ¤Ï¤¤¤Ä¤Ç¤â¤Ç¤­¡¢ Ää»ß (block) ¤µ¤ì¤ë¤³¤È¤â¤Ê¤¤¡£ ½¾¤Ã¤Æ¡¢¥½¥±¥Ã¥È¤Ë OOB ¥Ç¡¼¥¿¤Î½ñ¤­¹þ¤ß¤¬²Äǽ¤Ç¤¢¤ë¤«¤É¤¦¤«¤ò¥Á¥§¥Ã¥¯¤¹¤ë 4 ÈÖÌܤν¸¹ç¤ÏɬÍפʤ¤¤Î¤Ç¤¢¤ë¡£
nfds
Á´¤Æ¤Î½¸¹ç¤Ë´Þ¤Þ¤ì¤ë¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Î¤¦¤Á¡¢ Ãͤ¬ºÇÂç¤Î¤â¤Î¤Ë 1 ¤ò­¤·¤¿À°¿ô¤Ç¤¢¤ë¡£ ¤¹¤Ê¤ï¤Á¡¢¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ò½¸¹ç¤Ë²Ã¤¨¤ëºî¶È¤ÎÅÓÃæ¤Ç¡¢ Á´¤Æ¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ò¸«¤ÆºÇÂçÃͤòµá¤á¡¢ ¤½¤ì¤Ë 1 ¤ò²Ã¤¨¤Æ nfds ¤È¤·¤Æ select() ¤ËÅϤµ¤Ê¤¤¤È¤¤¤±¤Ê¤¤¡¢¤È¤¤¤¦¤³¤È¤À¡£
utimeout
(²¿¤âµ¯¤³¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë) select() ¤¬Ìá¤ëÁ°¤ËÂԤĺÇÂç»þ´Ö¤Ç¤¢¤ë¡£ ¤³¤ÎÃÍ¤Ë NULL ¤òÅϤ¹¤È¡¢ select() ¤Ï²¿¤é¤«¤Î¥¤¥Ù¥ó¥È¤òÂÔ¤Á¤Ä¤Å¤±¤Æ¤º¤Ã¤ÈÄä»ß¤¹¤ë¡£ utimeout ¤Ï 0 Éäˤ¹¤ë¤³¤È¤â¤Ç¤­¡¢ ¤³¤Î¾ì¹ç select() ¤Ïľ¤Á¤ËÌá¤ë¡£ ¹½Â¤ÂÎ struct timeval ¤Ï¼¡¤Î¤è¤¦¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤ë:

struct timeval {

    time_t tv_sec;    /* seconds */

    long tv_usec;     /* microseconds */

};

ntimeout
¤³¤Î°ú¤­¿ô¤Ï utimeout ¤ÈƱ¤¸°ÕÌ£¤ò»ý¤Ä¤¬¡¢ struct timespec ¤Ï¼¡¤Ë¼¨¤¹¤è¤¦¤Ë¥Ê¥ÎÉäÎÀºÅÙ¤ò»ý¤Ä¡£

struct timespec {

    long tv_sec;    /* seconds */

    long tv_nsec;   /* nanoseconds */

};

sigmask
¤³¤Î°ú¤­¿ô¤Ï pselect() ¥³¡¼¥ë¤Î¼Â¹ÔÃæ¤Ëµö²Ä¤µ¤ì¤ë ¥·¥°¥Ê¥ë¤Î½¸¹ç¤òÊÝ»ý¤¹¤ë (sigaddset(3) ¤ª¤è¤Ó sigprocmask(2) ¤ò»²¾È)¡£¤³¤ì¤Ë¤Ï NULL ¤òÅϤ¹¤³¤È¤â¤Ç¤­¡¢ ¤½¤Î¾ì¹ç¤Ï¤³¤Î´Ø¿ô¤ØÆþ¤ë¤È¤­¡¦½Ð¤ë¤È¤­¤Ëµö²Ä¥·¥°¥Ê¥ë¤Î½¸¹ç¤òÊѹ¹¤·¤Ê¤¤¡£ ¤½¤Î¸å¤Ï select() ¤ÈÁ´¤¯Æ±ÍͤÎÆ°ºî¤ò¤¹¤ë¡£

¥·¥°¥Ê¥ë¤È¥Ç¡¼¥¿¥¤¥Ù¥ó¥È¤òÁȤ߹ç¤ï¤»¤ë

¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤«¤é¡¢¥Ç¡¼¥¿¤À¤±¤Ç¤Ê¤¯¥·¥°¥Ê¥ë¤âÂÔ¤Á¤¿¤¤¤È¤­¤Ë¤Ï pselect() ¤ò»È¤¦É¬Íפ¬¤¢¤ë¡£¥·¥°¥Ê¥ë¤ò¥¤¥Ù¥ó¥È¤È¤·¤Æ¼õ¿®¤¹¤ë¥×¥í¥°¥é¥à¤Ï¡¢ ÂçÄñ¥·¥°¥Ê¥ë¥Ï¥ó¥É¥é¤ò¥°¥í¡¼¥Ð¥ë¤Ê¥Õ¥é¥°¤òΩ¤Æ¤ë¤¿¤á¤À¤±¤Ë»È¤¦¡£ ¤³¤Î¥°¥í¡¼¥Ð¥ë¤Ê¥Õ¥é¥°¤Ï¡¢ ¤½¤Î¥¤¥Ù¥ó¥È¤ò¥×¥í¥°¥é¥à¤Î¥á¥¤¥ó¥ë¡¼¥×¤Ç ½èÍý¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³¤È¤ò¼¨¤¹¡£ ¥·¥°¥Ê¥ë¤ò¼õ¤±¤ë¤È select() (¤ä pselect()) ¤Ï errno ¤Ë EINTR ¤ò¥»¥Ã¥È¤·¤ÆÌá¤ë¤³¤È¤Ë¤Ê¤ë¡£ ¥·¥°¥Ê¥ë¤¬¥×¥í¥°¥é¥à¤Î¥á¥¤¥ó¥ë¡¼¥×¤Ç½èÍý¤µ¤ì¤ë¤¿¤á¤Ë¤Ï¤³¤ÎÆ°ºî¤¬ÉԲķç¤Ç¡¢ ¤³¤ì¤¬¤Ê¤¤¤È select() ¤Ï±Ê±ó¤ËÄä»ß¤·Â³¤±¤ë¤³¤È¤Ë¤Ê¤ë¡£ ¤µ¤Æ¡¢¥á¥¤¥ó¥ë¡¼¥×¤Î¤É¤³¤«¤Ë¤³¤Î¥°¥í¡¼¥Ð¥ë¥Õ¥é¥°¤ò¥Á¥§¥Ã¥¯¤¹¤ë ¾ò·ïʸ¤¬¤¢¤ë¤È¤·¤è¤¦¡£¤³¤³¤Ç¾¯¤·¹Í¤¨¤Æ¤ß¤Ê¤¤¤È¤¤¤±¤Ê¤¤¡£ ¡Ö¥·¥°¥Ê¥ë¤¬¾ò·ïʸ¤Î¸å¡¢¤·¤«¤· select() ¥³¡¼¥ë¤ÎÁ°¤ËÅþÃ夷¤¿¤é ¤É¤¦¤Ê¤ë¤Î¤«¡©¡× Åú¤¨¤Ï¡Ö¤½¤Î select() ¤Ï¡¢¤¿¤È¤¨²ò·èÂÔ¤Á¤Î¥¤¥Ù¥ó¥È¤¬¤¢¤Ã¤¿¤È¤·¤Æ¤â¡¢ ±Ê±ó¤ËÄä»ß¤¹¤ë¡×¤Ç¤¢¤ë¡£ ¤³¤Î¶¥¹ç¾õÂÖ¤Ï pselect() ¥³¡¼¥ë¤Ë¤è¤Ã¤Æ²ò·è¤Ç¤­¤ë¡£ pselect() ¥³¡¼¥ë¤Ï¡¢¼«Ê¬¼«¿È¤ÎÆâÉô°Ê³°¤Ç¤Ï¼õ¿®¤·¤¿¤¯¤Ê¤¤¥·¥°¥Ê¥ë¤ò ¥Þ¥¹¥¯¤·¤Æ½ü³°¤¹¤ë¤Î¤Ë»ÈÍѤǤ­¤ë¡£ Î㤨¤Ð¡¢ÌäÂê¤È¤Ê¤Ã¤Æ¤¤¤ë¥¤¥Ù¥ó¥È¤¬»Ò¥×¥í¥»¥¹¤Î½ªÎ»¤Î¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£ ¥á¥¤¥ó¥ë¡¼¥×¤¬»Ï¤Þ¤ëÁ°¤Ë¡¢ SIGCHLD ¤ò sigprocmask(2) ¤Ç¥Ö¥í¥Ã¥¯¤¹¤ë¡£ pselect() ¥³¡¼¥ë¤Ç¤Ï SIGCHLD ¤ò¡¢¤â¤È¤â¤È¤Î¥·¥°¥Ê¥ë¥Þ¥¹¥¯¤ò »È¤Ã¤ÆÍ­¸ú¤Ë¤¹¤ë¤Î¤À¡£¤³¤Î¥×¥í¥°¥é¥à¤Ï¼¡¤Î¤è¤¦¤Ë¤Ê¤ë¡£

int child_events = 0;



void

child_sig_handler(int x)

{

    child_events++;

    signal(SIGCHLD, child_sig_handler);

}



int

main(int argc, char **argv)

{

    sigset_t sigmask, orig_sigmask;



    sigemptyset(&sigmask);

    sigaddset(&sigmask, SIGCHLD);

    sigprocmask(SIG_BLOCK, &sigmask, &orig_sigmask);



    signal(SIGCHLD, child_sig_handler);



    for (;;) { /* main loop */

        for (; child_events > 0; child_events--) {

            /* do event work here */

        }

        r = pselect(nfds, &rd, &wr, &er, 0, &orig_sigmask);



        /* main body of program */

    }

}

¼ÂÎã

¼ÂºÝ¤Î¤È¤³¤í select() ¤ÎÂç»ö¤ÊÅÀ¤Ï²¿¤Ê¤Î¤«¡© ¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Ï¹¥¤­¤Ê¤È¤­¤ËÆɤ߽ñ¤­¤Ç¤­¤ë¤ó¤¸¤ã¤Ê¤¤¤Î¡© select() ¤Î½ÅÍפʤȤ³¤í¤Ï¡¢Ê£¿ô¤Î¥Ç¥£¥¹¥¯¥ê¥×¥¿¤òƱ»þ¤Ë´Æ»ë¤Ç¤­¡¢ ¤Ê¤ó¤ÎÆ°¤­¤â¤Ê¤±¤ì¤Ð¥×¥í¥»¥¹¤òŬÀڤ˥¹¥ê¡¼¥×¾õÂ֤˰ܹԤ¹¤ë¤È¤³¤í¤Ë¤¢¤ë¤Î¤À¡£ select() ¤òÍѤ¤¤ì¤Ð¡¢Ê£¿ô¤Î¥Ñ¥¤¥×¤ä¥½¥±¥Ã¥È¤òƱ»þ¤Ë°·¤¤¤Ê¤¬¤é ¤³¤ì¤¬¹Ô¤¨¤ë¡£Unix ¥×¥í¥°¥é¥Þ¤Ï¡¢ Ê£¿ô¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ÎÆþ½ÐÎϤòƱ»þ¤Ë°·¤ï¤Í¤Ð¤Ê¤é¤º¡¢ ¤·¤«¤â¥Ç¡¼¥¿¤Îή¤ì¤Ï´Ö·çŪ¤Ç¤¢¤ë¡¢¤È¤¤¤¦¾õ¶·¤Ë¤è¤¯½Ð²ñ¤¦¡£ ñ¤Ë read(2) ¤ä write(2) ¥³¡¼¥ë¤Î¥·¡¼¥±¥ó¥¹¤òºî¤ë¤À¤±¤Ç¤Ï¡¢¤½¤ì¤é¤Î¥³¡¼¥ë¤Î¤É¤ì¤«¤¬ ¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤«¤é¤Î¥Ç¡¼¥¿¤òÂԤäƥ֥í¥Ã¥¯¤·¤Æ¤ª¤ê¡¢ ¾¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Ë¤Ï¥Ç¡¼¥¿¤¬ÅþÃ夷¤Æ¤¤¤ë¤Î¤Ë»È¤¨¤Ê¤¤¡¢ ¤È¤¤¤¦¤³¤È¤Ë¤Ê¤Ã¤Æ¤·¤Þ¤¦¤À¤í¤¦¡£ select() ¤ò»È¤¦¤È¤³¤Î¾õ¶·¤Ë¸ú²ÌŪ¤ËÂнè¤Ç¤­¤ë¡£

select() ¤ò»È¤Ã¤¿´Êñ¤ÊÎ㤬 select(2) ¤Î¥Þ¥Ë¥å¥¢¥ë¥Ú¡¼¥¸¤Ë½ñ¤«¤ì¤Æ¤¤¤ë¡£

SELECT ¤ÎÙÝ

select() ¤ò»È¤ª¤¦¤È¤·¤¿Â¿¤¯¤Î¿Í¤Ï¡¢Íý²ò¤·¤Ë¤¯¤¤µóÆ°¤Ë½Ð¤¯¤ï¤·¡¢·ë²ÌŪ¤Ë ¤Ç¤­¤¿¤â¤Î¤Ï°Ü¿¢À­¤¬¤Ê¤¤¤«¡¢¤è¤¯¤Æ¤â¥®¥ê¥®¥ê¤Î¤â¤Î¤Ë¤Ê¤Ã¤Æ¤·¤Þ¤¦¡£ Î㤨¤Ð¡¢¾åµ­¤Î¥×¥í¥°¥é¥à¤Ï¡¢ ½¸¹ç¤Ë´Þ¤Þ¤ì¤ë¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤òÈó¥Ö¥í¥Ã¥¯¥â¡¼¥É (ioctl(2) »²¾È) ¤Ë¤·¤Ê¤¯¤Æ¤â¡¢¤É¤³¤Ë¤â¥Ö¥í¥Ã¥¯¤¬À¸¤¸¤Ê¤¤¤è¤¦Ãí°Õ¤·¤Æ½ñ¤«¤ì¤Æ¤¤¤ë¡£ Èù̯¤Ê´Ö°ã¤¤¤Ë¤è¤Ã¤Æ¡¢ select() ¤ò»È¤¦ÍøÅÀ¤Ï´Êñ¤Ë¼º¤ï¤ì¤Æ¤·¤Þ¤¦¡£ ¤½¤³¤Ç¤³¤³¤Ç¤Ï¡¢ select() ¥³¡¼¥ë¤ò»È¤¦¤È¤­¤ËÃí°Õ¤¹¤Ù¤­½ÅÍ×»ö¹à¤ò¥ê¥¹¥È¤·¤è¤¦¤È»×¤¦¡£
1.
select() ¤ò»È¤¦¤È¤­¤Ï¡¢¥¿¥¤¥à¥¢¥¦¥È¤ÏÀßÄꤹ¤Ù¤­¤Ç¤Ê¤¤¡£ ½èÍý¤¹¤ë¥Ç¡¼¥¿¤¬Ìµ¤¤¤È¤­¤Ë¤Ï¡¢ ¤¢¤Ê¤¿¤Î¥×¥í¥°¥é¥à¤Ë¤Ï²¿¤â¤¹¤ë¤³¤È¤Ï̵¤¤¤Ï¤º¤Ç¤¢¤ë¡£ ¥¿¥¤¥à¥¢¥¦¥È¤Ë°Í¸¤·¤¿¥³¡¼¥É¤ÏÄ̾ï°Ü¿¢À­¤¬¤Ê¤¯¡¢ ¥Ç¥Ð¥Ã¥°¤âÆñ¤·¤¯¤Ê¤ë¡£
2.
¾å½Ò¤·¤¿¤è¤¦¤Ë¡¢ ¸úΨŪ¤Ê¥×¥í¥°¥é¥à¤ò½ñ¤¯¤Ë¤Ï nfds ¤ÎÃͤòŬÀڤ˷׻»¤·¤ÆÍ¿¤¨¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3.
select() ¥³¡¼¥ë¤Î½ªÎ»¸å¤Ë·ë²Ì¤ò¥Á¥§¥Ã¥¯¤·¤Æ¡¢ ŬÀÚ¤ËÂбþ¤¹¤ë¤Ä¤â¤ê¤Î¤Ê¤¤¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Ï¡¢ ¤É¤Î½¸¹ç¤Ë¤â²Ã¤¨¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ ¼¡¤Î¥ë¡¼¥ë¤â»²¾È¡£
4.
select() ¤«¤éÊ֤俸å¤Ë¤Ï¡¢Á´¤Æ¤Î½¸¹ç¤ÎÁ´¤Æ¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤Ë¤Ä¤¤¤Æ Æɤ߽ñ¤­²Äǽ¤Ê¾õÂ֤ˤʤäƤ¤¤ë¤«¤ò¥Á¥§¥Ã¥¯¤¹¤Ù¤­¤Ç¤¢¤ë¡£
5.
read(2), recv(2), write(2), send(2) ¤È¤¤¤Ã¤¿´Ø¿ô¤Ï¡¢¤³¤Á¤é¤¬Í׵ᤷ¤¿Á´¥Ç¡¼¥¿¤òÆɤ߽ñ¤­¤¹¤ëɬÍפϤʤ¤¡£ ¤â¤·Á´¥Ç¡¼¥¿¤òÆɤ߽ñ¤­¤¹¤ë¤Ê¤é¡¢¤½¤ì¤Ï¥È¥é¥Õ¥£¥Ã¥¯¤ÎÉé²Ù¤¬¾®¤µ¤¯¡¢ ¥¹¥È¥ê¡¼¥à¤¬Â®¤¤¾ì¹ç¤À¤í¤¦¡£¤³¤Î¾ò·ï¤Ï¾ï¤ËËþ¤¿¤µ¤ì¤ë¤È¤Ï¸Â¤é¤Ê¤¤¡£ ¤³¤ì¤é¤Î´Ø¿ô¤¬´èÄ¥¤Ã¤Æ¤â 1 ¥Ð¥¤¥È¤·¤«Á÷¼õ¿®¤Ç¤­¤Ê¤¤¤è¤¦¤Ê¾ì¹ç¤â ¹Íθ¤ËÆþ¤ì¤Æ¤ä¤é¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
6.
½èÍý¤¹¤ë¥Ç¡¼¥¿Î̤¬¾®¤µ¤¤¤³¤È¤¬¤Ï¤Ã¤­¤ê¤È¤ï¤«¤Ã¤Æ¤¤¤ë¾ì¹ç¤ò½ü¤¤¤Æ¡¢ °ìÅÙ¤Ë 1 ¥Ð¥¤¥È¤º¤ÄÆɤ߽ñ¤­¤¹¤ë¤è¤¦¤Ê¤³¤È¤Ï¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ ¥Ð¥Ã¥Õ¥¡¤Îµö¤¹¤«¤®¤ê¤Î¥Ç¡¼¥¿¤ò¤Þ¤È¤á¤ÆÆɤ߽ñ¤­¤·¤Ê¤¤¤È¡¢ Èó¾ï¤Ë¸úΨ¤¬°­¤¤¡£¾åµ­¤ÎÎã¤Ç¤Ï¥Ð¥Ã¥Õ¥¡¤Ï 1024 ¥Ð¥¤¥È¤Ë¤·¤Æ¤¤¤ë¤¬¡¢ ¤³¤Î¥µ¥¤¥º¤òÂ礭¤¯¤¹¤ë¤Î¤Ï´Êñ¤À¤í¤¦¡£
7.
read(2), recv(2), write(2), send(2) ¤Ê¤É¤Î´Ø¿ô¤ä select() ¥³¡¼¥ë¤Ï¡¢ errno ¤ò EINTR ¤ä EAGAIN (EWOULDBLOCK) ¤Ë¤·¤Æ -1 ¤òÊÖ¤¹¤³¤È¤¬¤¢¤ë¡£ ¤³¤Î¤è¤¦¤Ê·ë²Ì¤ËÂФ·¤ÆŬÀÚ¤ËÂбþ¤·¤Æ¤ä¤é¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤ (¾åµ­¤ÎÎã¤Ç¤Ï¤·¤Æ¤¤¤Ê¤¤)¡£ ½ñ¤¤¤Æ¤¤¤ë¥×¥í¥°¥é¥à¤¬¥·¥°¥Ê¥ë¤ò¼õ¤±¤ëͽÄ꤬¤Ê¤±¤ì¤Ð¡¢ EINTR ¤¬ÊÖ¤µ¤ì¤ë¤³¤È¤Ï¤¢¤Þ¤ê¹Í¤¨¤é¤ì¤Ê¤¤¡£ ½ñ¤¤¤Æ¤¤¤ë¥×¥í¥°¥é¥à¤ÇÈó¥Ö¥í¥Ã¥¯ I/O ¤ò¥»¥Ã¥È¤·¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï¡¢ EAGAIN ¤¬ÊÖ¤µ¤ì¤ë¤³¤È¤Ï¤Ê¤¤¤À¤í¤¦¡£¤½¤ì¤Ç¤â¤Ê¤ª¡¢ ´°Á´¤ò´ü¤¹¤ë¤Ê¤é¤Ð¡¢¤³¤ì¤é¤Î¥¨¥é¡¼¤ò¹Íθ¤ËÆþ¤ì¤ëɬÍפ¬¤¢¤ë¡£
8.
·è¤·¤Æ¡¢°ú¤­¿ô¤ËŤµ 0 ¤Î¥Ð¥Ã¥Õ¥¡¤ò»ØÄꤷ¤Æ read(2), recv(2), write(2), send(2) ¤ò¸Æ¤Ó½Ð¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
9.
read(2), recv(2), write(2), send(2) ¤¬ 7. ¤Ë¼¨¤·¤¿°Ê³°¤Î¥¨¥é¡¼¤Ç¼ºÇÔ¤·¤¿¾ì¹ç¤ä¡¢ ÆþÎϷϤδؿô¤Î°ì¤Ä¤¬¥Õ¥¡¥¤¥ëËöÈø¤òɽ¤¹ 0 ¤òÊÖ¤·¤¿¾ì¹ç¤Ï¡¢ ¤½¤Î¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ò¤â¤¦°ìÅÙ select ¤ËÅϤ·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ ¾åµ­¤ÎÎã¤Ç¤Ï¡¢¤½¤Î¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ò¤¿¤À¤Á¤Ë¥¯¥í¡¼¥º¤·¡¢ ¤½¤³¤Ë¤Ï -1 ¤ò¥»¥Ã¥È¤·¤Æ¡¢ ¤½¤ì¤¬½¸¹ç¤Ë´Þ¤Þ¤ì³¤±¤ë¤Î¤òµö¤µ¤Ê¤¤¤è¤¦¤Ë¤·¤Æ¤¤¤ë¡£
10.
¥¿¥¤¥à¥¢¥¦¥È¤ÎÃÍ¤Ï select() ¤ò¸Æ¤Ö¤¿¤Ó¤Ë½é´ü²½¤¹¤Ù¤­¤Ç¤¢¤ë¡£ OS ¤Ë¤è¤Ã¤Æ¤Ï timeout ¹½Â¤ÂΤ¬Êѹ¹¤µ¤ì¤ë¾ì¹ç¤¬¤¢¤ë¤«¤é¤Ç¤¢¤ë¡£ ⤷¡¢ pselect() ¤Ï¼«Ê¬¤Î timeout ¹½Â¤ÂΤòÊѹ¹¤¹¤ë¤³¤È¤Ï¤Ê¤¤¡£
11.
ʹ¤¤¤¿¤È¤³¤í¤Ç¤Ï¡¢Windows ¤Î¥½¥±¥Ã¥ÈÁØ¤Ï OOB ¥Ç¡¼¥¿¤òÀµ¤·¤¯½èÍý¤·¤Ê¤¤¤é¤·¤¤¡£ ¤Þ¤¿¡¢¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤¬Á´¤¯¥»¥Ã¥È¤µ¤ì¤Æ¤¤¤Ê¤¤¤è¤¦¤Ê select() ¥³¡¼¥ë¤âÀµ¤·¤¯½èÍý¤·¤Ê¤¤¤é¤·¤¤¡£ ¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ò°ìÀÚÀßÄꤷ¤Ê¤¤¤Ç timeout ¤ò»È¤¦¤ä¤êÊý¤Ï¡¢ 1 Éðʲ¼¤ÎÀºÅÙ¤Ç¥×¥í¥»¥¹¤ò¥¹¥ê¡¼¥×¤µ¤»¤ë¤Ë¤ÏÊØÍø¤ÊÊýË¡¤Ê¤Î¤À¤¬ (³¤­¤ò¸«¤è)¡£

usleep ¥¨¥ß¥å¥ì¡¼¥·¥ç¥ó

usleep(3) ´Ø¿ô¤ò»ý¤¿¤Ê¤¤¥·¥¹¥Æ¥à¤Ç¤Ï¡¢ Í­¸Â¤Î¥¿¥¤¥à¥¢¥¦¥È¤ò»ØÄꤷ¡¢¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤òÁ´¤¯¥»¥Ã¥È¤»¤º¤Ë select() ¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤Ç¡¢¤³¤ì¤òÂåÍѤǤ­¤ë¡£ °Ê²¼¤Î¤è¤¦¤Ë¤¹¤ë¡£

    struct timeval tv;

    tv.tv_sec = 0;

    tv.tv_usec = 200000;  /* 0.2 seconds */

    select(0, NULL, NULL, NULL, &tv);

⤷¡¢¤³¤ì¤¬Æ°¤¯¤ÈÊݾڤµ¤ì¤Æ¤¤¤ë¤Î¤Ï Unix ¥·¥¹¥Æ¥à¤Ë¸Â¤é¤ì¤ë¡£

ÊÖ¤êÃÍ

À®¸ù¤¹¤ë¤È¡¢ select() ¤Ï¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿½¸¹ç¤Ë»Ä¤Ã¤Æ¤¤¤ë ¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ÎÁí¿ô¤òÊÖ¤¹¡£

select() ¤¬¥¿¥¤¥à¥¢¥¦¥È¤¹¤ë¤È¡¢ÊÖ¤êÃÍ¤Ï 0 ¤Ë¤Ê¤ë¡£ ¤½¤Î»þ¡¢¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿½¸¹ç¤Ï¤¹¤Ù¤Æ¶õ¤Ç¤¢¤ë (¤·¤«¤·¤½¤¦¤Ê¤é¤Ê¤¤¥·¥¹¥Æ¥à¤â¤¢¤ë)¡£

ÊÖ¤êÃͤ¬ -1 ¤Î¾ì¹ç¤Ï¥¨¥é¡¼¤ò°ÕÌ£¤·¡¢ errno ¤¬Å¬Àڤ˥»¥Ã¥È¤µ¤ì¤ë¡£¥¨¥é¡¼¤¬µ¯¤³¤Ã¤¿¾ì¹ç¡¢ ÊÖ¤µ¤ì¤¿½¸¹ç¤ä timeout ¹½Â¤ÂΤÎÆâÍƤÏ̤ÄêµÁ¤È¤Ê¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢ »È¤¦¤Ù¤­¤Ç¤Ï¤Ê¤¤¡£ ¤·¤«¤· pselect() ¤Ï·è¤·¤Æ ntimeout ¤òÊѹ¹¤·¤Ê¤¤¡£

Ãí°Õ

°ìÈÌŪ¤Ë¸À¤Ã¤Æ¡¢¥½¥±¥Ã¥È¤ò¥µ¥Ý¡¼¥È¤¹¤ëÁ´¤Æ¤Î¥ª¥Ú¥ì¡¼¥Æ¥£¥ó¥°¥·¥¹¥Æ¥à¤Ï select() ¤â¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£ select() ¤ò»È¤ï¤Ê¤¤¤È¤â¤Î¤¹¤´¤¯Ê£»¨¤Ë¤Ê¤Ã¤Æ¤·¤Þ¤¦¥×¥í¥°¥é¥à¤¬Â¿¤¤¡£ select() ¤ò»È¤¦¤È¡¢¥×¥í¥°¥é¥Þ¤¬¥¹¥ì¥Ã¥É¡¢¥Õ¥©¡¼¥¯¡¢IPC¡¢¥·¥°¥Ê¥ë¡¢¥á¥â¥ê¶¦Í­¡¢ Åù¡¹¤ò»È¤Ã¤Æ¤â¤Ã¤ÈÊ£»¨¤ÊÊýË¡¤Ç²ò·è¤·¤è¤¦¤È¤¹¤ë¿¤¯¤ÎÌäÂ꤬¡¢ °Ü¿¢À­¤¬¤¢¤ê¤«¤Ä¸úΨŪ¤ÊÊýË¡¤Ç²ò·è¤Ç¤­¤ë¡£

poll(2) ¥·¥¹¥Æ¥à¥³¡¼¥ë¤Ï select() ¤ÈƱ¤¸µ¡Ç½¤ò»ý¤Ã¤Æ¤ª¤ê¡¢ ¤Þ¤Ð¤é¤Ê¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿½¸¹ç¤ò´Æ»ë¤¹¤ë¾ì¹ç¤Ë ¤¤¤¯¤é¤«¸úΨ¤¬¤è¤¤¡£ ¸½ºß¤Ç¤Ï¹­¤¯ÍøÍѲÄǽ¤Ç¤¢¤ë¤¬¡¢°ÊÁ°¤Ï select() ¤è¤ê°Ü¿¢À­¤ÎÌ̤ÇÎô¤Ã¤Æ¤¤¤¿¡£

Linux Æȼ«¤Î epoll(7) API ¤Ï¡¢Â¿¿ô¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿¤ò´Æ»ë¤¹¤ë¾ì¹ç¤Ë select(2) ¤ä poll(2) ¤è¤ê¤â¸úΨŪ¤Ê¥¤¥ó¥¿¥Õ¥§¡¼¥¹¤òÄ󶡤·¤Æ¤¤¤ë¡£

Îã

select() ¤ÎËÜÅö¤ËÊØÍø¤ÊÅÀ¤ò¼¨¤¹¡¢¤è¤¤Îã¤ò¾Ò²ð¤¹¤ë¡£ °Ê²¼¤Î¥ê¥¹¥È¤Ï¡¢¤¢¤ë TCP ¥Ý¡¼¥È¤«¤éÊ̤Υݡ¼¥È¤ØžÁ÷¤ò¹Ô¤¦ TCP ¥Õ¥©¥ï¡¼¥É¥×¥í¥°¥é¥à¤Ç¤¢¤ë¡£

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

#include <sys/time.h>

#include <sys/types.h>

#include <string.h>

#include <signal.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <errno.h>



static int forward_port;



#undef max

#define max(x,y) ((x) > (y) ? (x) : (y))



static int

listen_socket(int listen_port)

{

    struct sockaddr_in a;

    int s;

    int yes;

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {

        perror("socket");

        return -1;

    }

    yes = 1;

    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,

            (char *) &yes, sizeof(yes)) < 0) {

        perror("setsockopt");

        close(s);

        return -1;

    }

    memset(&a, 0, sizeof(a));

    a.sin_port = htons(listen_port);

    a.sin_family = AF_INET;

    if (bind(s, (struct sockaddr *) &a, sizeof(a)) < 0) {

        perror("bind");

        close(s);

        return -1;

    }

    printf("accepting connections on port %d\n", listen_port);

    listen(s, 10);

    return s;

}



static int

connect_socket(int connect_port, char *address)

{

    struct sockaddr_in a;

    int s;

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {

        perror("socket");

        close(s);

        return -1;

    }



    memset(&a, 0, sizeof(a));

    a.sin_port = htons(connect_port);

    a.sin_family = AF_INET;



    if (!inet_aton(address, (struct in_addr *) &a.sin_addr.s_addr)) {

        perror("bad IP address format");

        close(s);

        return -1;

    }



    if (connect(s, (struct sockaddr *) &a, sizeof(a)) < 0) {

        perror("connect()");

        shutdown(s, SHUT_RDWR);

        close(s);

        return -1;

    }

    return s;

}



#define SHUT_FD1 {                      \

        if (fd1 >= 0) {                 \

            shutdown(fd1, SHUT_RDWR);   \

            close(fd1);                 \

            fd1 = -1;                   \

        }                               \

    }



#define SHUT_FD2 {                      \

        if (fd2 >= 0) {                 \

            shutdown(fd2, SHUT_RDWR);   \

            close(fd2);                 \

            fd2 = -1;                   \

        }                               \

    }



#define BUF_SIZE 1024



int

main(int argc, char **argv)

{

    int h;

    int fd1 = -1, fd2 = -1;

    char buf1[BUF_SIZE], buf2[BUF_SIZE];

    int buf1_avail, buf1_written;

    int buf2_avail, buf2_written;



    if (argc != 4) {

        fprintf(stderr,

                 "Usage\n\tfwd <listen-port> "

                 "<forward-to-port> <forward-to-ip-address>\n");

        exit(EXIT_FAILURE);

    }



    signal(SIGPIPE, SIG_IGN);



    forward_port = atoi(argv[2]);



    h = listen_socket(atoi(argv[1]));

    if (h < 0)

        exit(EXIT_FAILURE);



    for (;;) {

        int r, nfds = 0;

        fd_set rd, wr, er;

        FD_ZERO(&rd);

        FD_ZERO(&wr);

        FD_ZERO(&er);

        FD_SET(h, &rd);

        nfds = max(nfds, h);

        if (fd1 > 0 && buf1_avail < BUF_SIZE) {

            FD_SET(fd1, &rd);

            nfds = max(nfds, fd1);

        }

        if (fd2 > 0 && buf2_avail < BUF_SIZE) {

            FD_SET(fd2, &rd);

            nfds = max(nfds, fd2);

        }

        if (fd1 > 0

            && buf2_avail - buf2_written > 0) {

            FD_SET(fd1, &wr);

            nfds = max(nfds, fd1);

        }

        if (fd2 > 0

            && buf1_avail - buf1_written > 0) {

            FD_SET(fd2, &wr);

            nfds = max(nfds, fd2);

        }

        if (fd1 > 0) {

            FD_SET(fd1, &er);

            nfds = max(nfds, fd1);

        }

        if (fd2 > 0) {

            FD_SET(fd2, &er);

            nfds = max(nfds, fd2);

        }



        r = select(nfds + 1, &rd, &wr, &er, NULL);



        if (r == -1 && errno == EINTR)

            continue;

        if (r < 0) {

            perror("select()");

            exit(EXIT_FAILURE);

        }

        if (FD_ISSET(h, &rd)) {

            unsigned int l;

            struct sockaddr_in client_address;

            memset(&client_address, 0, l = sizeof(client_address));

            r = accept(h, (struct sockaddr *) &client_address, &l);

            if (r < 0) {

                perror("accept()");

            } else {

                SHUT_FD1;

                SHUT_FD2;

                buf1_avail = buf1_written = 0;

                buf2_avail = buf2_written = 0;

                fd1 = r;

                fd2 =

                    connect_socket(forward_port, argv[3]);

                if (fd2 < 0) {

                    SHUT_FD1;

                } else

                    printf("connect from %s\n",

                            inet_ntoa(client_address.sin_addr));

            }

        }

/* NB: read oob data before normal reads */

        if (fd1 > 0)

            if (FD_ISSET(fd1, &er)) {

                char c;

                errno = 0;

                r = recv(fd1, &c, 1, MSG_OOB);

                if (r < 1) {

                    SHUT_FD1;

                } else

                    send(fd2, &c, 1, MSG_OOB);

            }

        if (fd2 > 0)

            if (FD_ISSET(fd2, &er)) {

                char c;

                errno = 0;

                r = recv(fd2, &c, 1, MSG_OOB);

                if (r < 1) {

                    SHUT_FD1;

                } else

                    send(fd1, &c, 1, MSG_OOB);

            }

        if (fd1 > 0)

            if (FD_ISSET(fd1, &rd)) {

                r =

                    read(fd1, buf1 + buf1_avail,

                          BUF_SIZE - buf1_avail);

                if (r < 1) {

                    SHUT_FD1;

                } else

                    buf1_avail += r;

            }

        if (fd2 > 0)

            if (FD_ISSET(fd2, &rd)) {

                r =

                    read(fd2, buf2 + buf2_avail,

                          BUF_SIZE - buf2_avail);

                if (r < 1) {

                    SHUT_FD2;

                } else

                    buf2_avail += r;

            }

        if (fd1 > 0)

            if (FD_ISSET(fd1, &wr)) {

                r =

                    write(fd1, buf2 + buf2_written,

                           buf2_avail - buf2_written);

                if (r < 1) {

                    SHUT_FD1;

                } else

                    buf2_written += r;

            }

        if (fd2 > 0)

            if (FD_ISSET(fd2, &wr)) {

                r =

                    write(fd2, buf1 + buf1_written,

                           buf1_avail - buf1_written);

                if (r < 1) {

                    SHUT_FD2;

                } else

                    buf1_written += r;

            }

/* check if write data has caught read data */

        if (buf1_written == buf1_avail)

            buf1_written = buf1_avail = 0;

        if (buf2_written == buf2_avail)

            buf2_written = buf2_avail = 0;

/* one side has closed the connection, keep

   writing to the other side until empty */

        if (fd1 < 0 && buf1_avail - buf1_written == 0) {

            SHUT_FD2;

        }

        if (fd2 < 0 && buf2_avail - buf2_written == 0) {

            SHUT_FD1;

        }

    }

    exit(EXIT_SUCCESS);

}

¾åµ­¤Î¥×¥í¥°¥é¥à¤Ï¡¢¤Û¤È¤ó¤É¤Î¼ïÎà¤Î TCP Àܳ¤ò¥Õ¥©¥ï¡¼¥É¤¹¤ë¡£ telnet ¥µ¡¼¥Ð¤Ë¤è¤Ã¤ÆÃæ·Ñ¤µ¤ì¤ë OOB ¥·¥°¥Ê¥ë¥Ç¡¼¥¿¤â°·¤¨¤ë¡£ ¤³¤Î¥×¥í¥°¥é¥à¤Ï¡¢¥Ç¡¼¥¿¥Õ¥í¡¼¤òÁÐÊý¸þ¤ËƱ»þ¤ËÁ÷¤ë¤È¤¤¤¦¡¢ ¤ä¤ä¤³¤·¤¤ÌäÂê¤â½èÍý¤Ç¤­¤ë¡£ fork(2) ¥³¡¼¥ë¤ò»È¤Ã¤Æ¡¢³Æ¥¹¥È¥ê¡¼¥à¤´¤È¤ËÀìÍѤΥ¹¥ì¥Ã¥É¤òÍѤ¤¤ë¤Û¤¦¤¬¸úΨŪ¤À¡¢ ¤È¤¤¤¦¿Í¤â¤¤¤ë¤«¤â¤·¤ì¤Ê¤¤¡£¤·¤«¤·¡¢¤³¤ì¤Ï¹Í¤¨¤Æ¤¤¤ë¤è¤ê¤º¤Ã¤È¤ä¤ä¤³¤·¤¤¡£ ¤¢¤ë¤¤¤Ï¡¢ ioctl(2) ¥³¡¼¥ë¤ò»È¤Ã¤ÆÈó¥Ö¥í¥Ã¥¯ I/O ¤ò¥»¥Ã¥È¤¹¤ì¤ÐÎɤ¤¡¢¤È¤¤¤¦¥¢¥¤¥Ç¥¢¤â¤¢¤ë¤À¤í¤¦¡£ ¤³¤ì¤Ë¤â¼ÂºÝ¤Ë¤ÏÌäÂ꤬¤¢¤ê¡¢¥¿¥¤¥à¥¢¥¦¥È¤¬Èó¸úΨŪ¤Ëµ¯¤³¤Ã¤Æ¤·¤Þ¤¦¡£

¤³¤Î¥×¥í¥°¥é¥à¤Ï°ìÅ٤ˤҤȤİʾå¤ÎƱ»þÀܳ¤ò°·¤¦¤³¤È¤Ï¤Ç¤­¤Ê¤¤¤¬¡¢ ¤½¤ÎÍͤ˳ÈÄ¥¤¹¤ë¤Î¤Ï´Êñ¤Ç¡¢¥Ð¥Ã¥Õ¥¡¤Î¥ê¥ó¥¯¥ê¥¹¥È¤ò (Àܳ¤´¤È¤Ë¤Ò¤È¤Ä¤º¤Ä) »È¤¨¤Ð¤è¤¤¡£ ¸½»þÅÀ¤Î¤â¤Î¤Ç¤Ï¡¢¿·¤·¤¤Àܳ¤¬¤¯¤ë¤È¸Å¤¤Àܳ¤ÏÍî¤Á¤Æ¤·¤Þ¤¦¡£

´ØÏ¢¹àÌÜ

accept(2), connect(2), ioctl(2), poll(2), read(2), recv(2), select(2), send(2), sigprocmask(2), write(2), sigaddset(3), sigdelset(3), sigemptyset(3), sigfillset(3), sigismember(3), epoll(7)