ºìÁªLinuxÃÅ»§
Linux°ïÖú

Linuxϸ÷ÀàTCPÍøÂç·þÎñÆ÷µÄʵÏÖÔ´´úÂë

·¢²¼Ê±¼ä:2006-07-06 22:56:08À´Ô´:ºìÁª×÷Õß:zhoulifa
´ó¼Ò¶¼ÖªµÀ¸÷ÀàÍøÂç·þÎñÆ÷³ÌÐòµÄ±àд²½Ö裬²¢ÇÒ¶¼ÖªµÀÍøÂç·þÎñÆ÷¾ÍÁ½´óÀࣺѭ»··þÎñºÍ²¢·¢·þÎñ¡£ÕâÀ︽ÉÏÔ´´úÂëÀ´¸öС½á°É¡£

Ê×ÏÈ£¬Ñ­»·ÍøÂç·þÎñÆ÷±à³ÌʵÏֵIJ½ÖèÊÇÕâÑùµÄ£º

ÕâÖÖ·þÎñÆ÷Ä£ÐÍÊǵäÐÍÑ­»··þÎñ£¬Èç¹û²»¼ÓÉ϶à½ø³Ì/Ï̼߳¼Êõ£¬´ËÖÖ·þÎñÍÌÍÂÁ¿ÓÐÏÞ£¬´ó¼Ò¶¼¿ÉÒÔ¿´µ½£¬Èç¹ûÇ°Ò»¸öÁ¬½Ó·þÎñÊý¾ÝûÓÐÊÕ·¢Íê±ÏºóÃæµÄÁ¬½Óû°ì·¨´¦Àí¡£ËùÒÔÒ»°ãÓжà½ø³Ì¼¼Êõ£¬¶ÔÒ»¸öÐÂÁ¬½ÓÆôÓÃÒ»¸öнø³ÌÈ¥´¦Àí£¬¶ø¼àÌýsocket¼ÌÐø¼àÌý¡£

/************¹ØÓÚ±¾Îĵµ********************************************
*filename: Linuxϸ÷ÀàTCPÍøÂç·þÎñÆ÷µÄʵÏÖÔ´´úÂë
*purpose: ¼Ç¼Linuxϸ÷Ààtcp·þÎñ³ÌÐòÔ´´úÂë
*wrote by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)
Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ
*date time:2006-07-04 22:00:00
*Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;
* µ«Çë×ñÑ­GPL
*Hope:Ï£ÍûÔ½À´Ô½¶àµÄÈ˹±Ï××Ô¼ºµÄÁ¦Á¿£¬Îª¿Æѧ¼¼Êõ·¢Õ¹³öÁ¦
*********************************************************************/

Ò»¸öÑ­»·TCP·þÎñÔ´´úÂ루ÒòΪÓÃfork½øÐжà½ø³Ì·þÎñÁË£¬ËùÒÔÕâÖÖ·þÎñÏÖʵÖÐÒ²ÓÐÓã©ÈçÏ£º
[CODE]
/*----------------------Ô´´úÂ뿪ʼ--------------------------------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
/*********************************************************************
*filename: cycletcpserver.c
*purpose: Ñ­»·tcp·þÎñ¶Ë³ÌÐò
*tidied by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)
Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ
*date time:2006-07-04 22:00:00
*Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;
* µ«Çë×ñÑ­GPL
*Thanks to: Google.com
*********************************************************************/
int main(int argc, char ** argv)
{
int sockfd,new_fd; /* ¼àÌýsocket: sock_fd,Êý¾Ý´«Êäsocket: new_fd */
struct sockaddr_in my_addr; /* ±¾»úµØÖ·ÐÅÏ¢ */
struct sockaddr_in their_addr; /* ¿Í»§µØÖ·ÐÅÏ¢ */
unsigned int sin_size, myport, lisnum;

if(argv[1]) myport = atoi(argv[1]);
else myport = 7838;

if(argv[2]) lisnum = atoi(argv[2]);
else lisnum = 2;

if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
my_addr.sin_family=PF_INET;
my_addr.sin_port=htons(myport);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 0);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}

if (listen(sockfd, lisnum) == -1) {
perror("listen");
exit(1);
}
while(1) {
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
continue;
}
printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
if (!fork()) { /* ×Ó½ø³Ì´úÂë¶Î */
if (send(new_fd, "Hello, world!\n", 14, 0) == -1) {
perror("send");
close(new_fd);
exit(0);
}
}
close(new_fd); /*¸¸½ø³Ì²»ÔÙÐèÒª¸Ãsocket*/
waitpid(-1,NULL,WNOHANG);/*µÈ´ý×Ó½ø³Ì½áÊø£¬Çå³ý×Ó½ø³ÌËùÕ¼ÓÃ×ÊÔ´*/
}
}
/*----------------------Ô´´úÂë½áÊø--------------------------------------------*/
[/CODE]
Ò»¸ö²âÊÔ¿Í»§¶Ë´úÂëÈçÏÂ
[CODE]
/*----------------------Ô´´úÂ뿪ʼ--------------------------------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXDATASIZE 100 /*ÿ´Î×î´óÊý¾Ý´«ÊäÁ¿ */
/*********************************************************************
*filename: cycletcpclient.c
*purpose: Ñ­»·tcp¿Í»§¶Ë³ÌÐò
*tidied by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)
Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ
*date time:2006-07-04 22:20:00
*Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;
* µ«Çë×ñÑ­GPL
*Thanks to: Google.com
*Hope:Ï£ÍûÔ½À´Ô½¶àµÄÈ˹±Ï××Ô¼ºµÄÁ¦Á¿£¬Îª¿Æѧ¼¼Êõ·¢Õ¹³öÁ¦
*********************************************************************/

int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr;
unsigned int myport;

if(argv[2]) myport = atoi(argv[2]);
else myport = 7838;

if (argc != 3) {
fprintf(stderr,"usage: %s hostname port\n", argv[0]);
exit(1);
}
if((he=gethostbyname(argv[1]))==NULL) {
herror("gethostbyname");
exit(1);
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
their_addr.sin_family=PF_INET;
their_addr.sin_port=htons(myport);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(their_addr.sin_zero),0);
if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
if ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = 0;
printf("Received: %s\n",buf);
close(sockfd);
return 0;
}
/*----------------------Ô´´úÂë½áÊø--------------------------------------------*/
[/CODE]
ÓÃgcc cycletcpserver.c -o tcpserverºÍgcc cycletcpclient.c -o tcpclient·Ö±ð±àÒëÉÏÊö´úÂëºóÔËÐÐÇé¿öÈçÏ£º
·þÎñ¶ËÔËÐÐÏÔʾ£º
ÒýÓÃ:

administrator@ubuzlf:/data/example/c$ ./tcpserver
server: got connection from 127.0.0.1
server: got connection from 127.0.0.1
server: got connection from 127.0.0.1

¿Í»§¶ËÔËÐÐÏÔʾ£º
ÒýÓÃ:

administrator@ubuzlf:/data/example/c$ ./tcpclient 127.0.0.1 7838
Received: Hello, world!

administrator@ubuzlf:/data/example/c$ ./tcpclient 127.0.0.1 7838
Received: Hello, world!

administrator@ubuzlf:/data/example/c$ ./tcpclient 127.0.0.1 7838
Received: Hello, world!

²»µÃ²»ËµµÄÒ»¸ö¸ÅÄîÐÔÎÊÌ⣺×èÈûÓë·Ç×èÈû
ÔÚ×èÈû·þÎñÖУ¬µ±·þÎñÆ÷ÔËÐе½acceptÓï¾ä¶øûÓпͻ§Á¬½Ó·þÎñÇëÇóµ½À´£¬ÄÇô»á·¢ÉúʲôÇé¿ö? Õâʱ·þÎñÆ÷¾Í»áÍ£Ö¹ÔÚacceptÓï¾äÉϵȴýÁ¬½Ó·þÎñÇëÇóµÄµ½À´£»Í¬Ñù£¬µ±³ÌÐòÔËÐе½½ÓÊÕÊý¾ÝÓï¾ärecvʱ£¬Èç¹ûûÓÐÊý¾Ý¿ÉÒÔ¶ÁÈ¡£¬Ôò³ÌÐòͬÑù»áÍ£Ö¹ÔÚ½ÓÊÕÓï¾äÉÏ¡£ÕâÖÖÇé¿ö³ÆΪ×èÈû(blocking)¡£
µ«Èç¹ûÄãÏ£Íû·þÎñÆ÷½ö½ö×¢Òâ¼ì²éÊÇ·ñÓпͻ§ÔڵȴýÁ¬½Ó£¬ÓоͽÓÊÜÁ¬½Ó;·ñÔò¾Í¼ÌÐø×öÆäËûÊÂÇ飬Ôò¿ÉÒÔͨ¹ý½« socketÉèÖÃΪ·Ç×èÈû·½Ê½À´ÊµÏÖ:·Ç×èÈûsocketÔÚûÓпͻ§Ôڵȴýʱ¾Íʹacceptµ÷ÓÃÁ¢¼´·µ»Ø ¡£
ͨ¹ýÉèÖÃsocketΪ·Ç×èÈû·½Ê½£¬¿ÉÒÔʵÏÖ¡°ÂÖѯ¡±Èô¸Ésocket¡£µ±Æóͼ´ÓÒ»¸öûÓÐÊý¾ÝµÈ´ý´¦ÀíµÄ·Ç×èÈûsocket¶ÁÈëÊý¾Ýʱ£¬º¯Êý½«Á¢¼´·µ»Ø£¬²¢ÇÒ·µ»ØÖµÖÃΪ-1£¬²¢ÇÒerrnoÖÃΪEWOULDBLOCK¡£µ«ÊÇÕâÖÖ¡°ÂÖѯ¡±»áʹCPU´¦ÓÚæµÈ´ý·½Ê½£¬´Ó¶ø½µµÍÐÔÄÜ¡£¿¼Âǵ½ÕâÖÖÇé¿ö£¬¼ÙÉèÄãÏ£Íû·þÎñÆ÷¼àÌýÁ¬½Ó·þÎñÇëÇóµÄͬʱ´ÓÒѾ­½¨Á¢µÄÁ¬½Ó¶ÁÈ¡Êý¾Ý£¬ÄãÒ²Ðí»áÏëµ½ÓÃÒ»¸öacceptÓï¾äºÍ¶à¸örecv()Óï¾ä£¬µ«ÊÇÓÉÓÚaccept¼°recv¶¼ÊÇ»á×èÈûµÄ£¬ËùÒÔÕâ¸öÏë·¨ÏÔÈ»²»»á³É¹¦¡£
µ÷Ó÷Ç×èÈûµÄsocket»á´ó´óµØÀË·Ñϵͳ×ÊÔ´¡£¶øµ÷ÓÃselect()»áÓÐЧµØ½â¾öÕâ¸öÎÊÌ⣬ËüÔÊÐíÄã°Ñ½ø³Ì±¾Éí¹ÒÆðÀ´£¬¶øͬʱʹϵͳÄں˼àÌýËùÒªÇóµÄÒ»×éÎļþÃèÊö·ûµÄÈκλ£¬Ö»ÒªÈ·ÈÏÔÚÈκα»¼à¿ØµÄÎļþÃèÊö·ûÉϳöÏֻ£¬select()µ÷Óý«·µ»Øָʾ¸ÃÎļþÃèÊö·ûÒÑ×¼±¸ºÃµÄÐÅÏ¢£¬´Ó¶øʵÏÖÁËΪ½ø³ÌÑ¡³öËæ»úµÄ±ä»¯£¬¶ø²»±ØÓɽø³Ì±¾Éí¶ÔÊäÈë½øÐвâÊÔ¶øÀË·ÑCPU¿ªÏú¡£

Æä´Î£¬²¢·¢·þÎñÆ÷£¬ÔÚÉÏÊöcycletcpserver.cÖУ¬ÓÉÓÚʹÓÃÁËfork¼¼ÊõÒ²¿ÉÒÔ³Æ֮Ϊ²¢·¢·þÎñÆ÷£¬µ«ÕâÖÖ·þÎñÆ÷²¢²»ÊÇÕæÕýÒâÒåÉϵÄIO¶à·¸´ÓõIJ¢·¢·þÎñÆ÷£¬²¢ÇÒÓÉÓÚûÓд¦Àí×èÈûÎÊÌ⣬ʵ¼ÊÓ¦ÓÃÓи÷ÖÖ¸÷ÑùµÄÎÊÌâ¡£

Ò»¸öµäÐÍIO¶à·¸´Óõĵ¥½ø³Ì²¢·¢·þÎñÆ÷Á÷³ÌÈçÏ£º
/*IO¶à·¸´Óò¢·¢·þÎñÁ÷³Ìͼ*/

ÏÂÃæÊÇÒ»¸öÑÝʾIO¶à·¸´ÓõÄÔ´³ÌÐò£¬ÊÇÒ»¸ö¶Ë¿Úת·¢³ÌÐò£¬µ«ËüµÄÓô¦Ï൱´ó£¬Êµ¼ÊÓ¦ÓÃÖеĸ÷Àà´úÀíÈí¼þ»ò¶Ë¿ÚÓ³ÉäÈí¼þ¶¼ÊÇ»ùÓÚÕâÑùµÄ´úÂëµÄ£¬±ÈÈçWindowsϵÄWinGate¡¢WinProxyµÈ¶¼ÊÇÔÚ´Ë»ù´¡ÉÏʵÏֵġ£Ô´´úÂëÈçÏ£º
[CODE]
/*----------------------Ô´´úÂ뿪ʼ--------------------------------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

static int forward_port;

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

/*************************¹ØÓÚ±¾Îĵµ************************************
*filename: tcpforwardport.c
*purpose: ÑÝʾÁËselectµÄÓ÷¨£¬ÕâÊÇÒ»¸ö¼«ºÃµÄ´úÀíÈí¼þºËÐÄ£¬×¨ÃÅ×÷¶Ë¿ÚÓ³ÉäÓÃ
*tidied by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)
Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ
*date time:2006-07-05 19:00:00
*Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;
* µ«Çë×ñÑ­GPL
*Thanks to: Paul Sheer ¸ÐлPaul SheerÔÚselect_tutµÄmanÊÖ²áÀïÌṩÁËÕâ·ÝÔ´´úÂë
*Hope:Ï£ÍûÔ½À´Ô½¶àµÄÈ˹±Ï××Ô¼ºµÄÁ¦Á¿£¬Îª¿Æѧ¼¼Êõ·¢Õ¹³öÁ¦
*********************************************************************/

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", (int) 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 \n");
exit (1);
}

signal (SIGPIPE, SIG_IGN);

forward_port = atoi (argv[2]);

/*½¨Á¢¼àÌýsocket*/
h = listen_socket (atoi (argv[1]));
if (h < 0) exit (1);

for (;;) {
int r, nfds = 0;
fd_set rd, wr, er;
FD_ZERO (&rd);
FD_ZERO (&wr);
FD_ZERO (&er);
FD_SET (h, &rd);

/*°Ñ¼àÌýsocketºÍ¿É¶ÁsocketÈý¸öÒ»Æð·ÅÈëselectµÄ¿É¶Á¾ä±úÁбíÀï*/
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);
}

/*°Ñ¿ÉдsocketÁ½¸öÒ»Æð·ÅÈëselectµÄ¿Éд¾ä±úÁбíÀï*/
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);
}

/*°ÑÓÐÒì³£Êý¾ÝµÄsocketÁ½¸öÒ»Æð·ÅÈëselectµÄÒì³£¾ä±úÁбíÀï*/
if (fd1 > 0) {
FD_SET (fd1, &er);
nfds = max (nfds, fd1);
}
if (fd2 > 0) {
FD_SET (fd2, &er);
nfds = max (nfds, fd2);
}

/*¿ªÊ¼select*/
r = select (nfds + 1, &rd, &wr, &er, NULL);

if (r == -1 && errno == EINTR) continue;
if (r < 0) {
perror ("select()");
exit (1);
}

/*´¦ÀíÐÂÁ¬½Ó*/
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 {
/*¹Ø±ÕÔ­ÓÐÁ¬½Ó£¬°ÑÐÂÁ¬½Ó×÷Ϊfd1£¬Í¬Ê±Á¬½ÓеÄÄ¿±êfd2*/
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);
}

/* NB: read data from fd1 */
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;
}

/* NB: read data from fd2 */
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;
}

/* NB: write data to fd1 */
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;
}

/* NB: write data to fd1 */
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;
}
}
return 0;
}
/*----------------------Ô´´úÂë½áÊø--------------------------------------------*/
[/CODE]
ÓÃgcc tcpforwardport.c -o MyProxy±àÒë´Ë³ÌÐòºóÔËÐÐЧ¹ûÈçÏ£º
ÒýÓÃ:

./MyProxy 8000 80 172.16.100.218
accepting connections on port 8000
connect from 127.0.0.1

µ±ÓÐÓû§·ÃÎʱ¾»úµÄ8000¶Ë¿Úʱ£¬MyProxy³ÌÐò½«°Ñ´ËÇëÇóת·¢µ½172.16.100.218Ö÷»úµÄ80¶Ë¿Ú£¬¼´ÊµÏÖÁËÒ»¸öhttp´úÀí¡£

¹ØÓÚselectº¯Êý£º
Æ亯ÊýÔ­ÐÍΪ£º
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
´Ëº¯ÊýµÄ¹¦ÄÜÊÇÓÉÄں˼ì²âÔÚtimeoutʱ¼äÄÚ£¬ÊÇ·ñÓÐreadfds£¬writefds£¬exceptfdsÈý¸ö¾ä±ú¼¯(file descriptors)ÀïµÄij¸ö¾ä±ú£¨file descriptor)µÄ״̬·ûºÏÑ°Ç󣬼´readfds¾ä±ú¼¯ÀïÓоä±ú¿É¶Á»òwritefds¾ä±ú¼¯ÀïÓпÉд»òexceptfds¾ä±ú¼¯ÀïÓÐÀýÍâ·¢Éú£¬ÈκÎÒ»¸öÓб仯º¯Êý¾ÍÁ¢¼´·µ»Ø£¬·µ»ØֵΪtimeout·¢Éú״̬±ä»¯µÄ¾ä±ú¸öÊý¡£
nÊÇËùÓÐreadfds£¬writefds£¬exceptfdsÈý¸ö¾ä±ú¼¯(file descriptors)Àï±àºÅ×î´óÖµ¼Ó1¡£±ÈÈ磺Ҫ¼ì²âÁ½¸ösocket¾ä±úfd1ºÍfd2ÔÚtimeoutʱ¼äÄÚÊÇ·ñ·Ö±ð¿É¶ÁºÍ¿Éд¾Í¿ÉÒÔÕâÑù£º
ÏÈ°ÑÁ½¸ö¾ä±ú¼¯(file descriptors)ÇåÁ㣺
FD_ZERO (&readfds);
FD_ZERO (&writefds);
È»ºó°Ñfd1¼ÓÈë¶Á¼ì²â¼¯£º
FD_SET (fd1, &readfds);
È»ºó°Ñfd2¼ÓÈëд¼ì²â¼¯£º
FD_SET (fd2, &writefds);
ÔÙ¸øtimeoutÉèÖÃÖµ£¬timeoutÊÇÕâÑùµÄÒ»¸ö½á¹¹£º
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
Äã¿ÉÒÔÕâÑù¸³Öµ£º
timeout.tv_sec=1;
timeout.tv_uec=0;
±íʾ¼ì²âÔÚ1ÃëÖÓÄÚÊÇ·ñÓоä±ú״̬·¢Éú±ä»¯¡£
Èç¹ûÓоä±ú·¢Éú±ä»¯£¬¾Í¿ÉÒÔÓÃFD_ISSET¼ì²â¸÷¸ö¾ä±ú£¬±ÈÈ磺
FD_ISSET (fd1, &readfds);//¼ì²âÊÇ·ñfd1±ä³É¿É¶ÁµÄÁË
FD_ISSET (fd2, &writefds);//¼ì²âÊÇ·ñfd2±ä³É¿ÉдµÄÁË
ʾÒâ³ÌÐò´úÂëÈçÏ£º
[CODE]
/*----------------------ʾÒâ´úÂ뿪ʼ--------------------------------------------*/
fd1 = socket();//´´½¨Ò»¸ösocket
fd2 = socket();//´´½¨Ò»¸ösocket
while(1) {
FD_ZERO (&readfds);
FD_ZERO (&writefds);
FD_SET (fd1, &readfds);
FD_SET (fd2, &writefds);
timeout.tv_sec=1;
timeout.tv_uec=0;
ret = select(fd1>fd2?(fd1+1):(fd2+1), &readfds, &writefds, NULL, &timeout);
if(ret < 0) {printf("ϵͳ´íÎó£¬select³ö´í£¬´íÎó´úÂ룺%d, ´íÎóÐÅÏ¢£º%s", errno, strerror(errno));}
else if(ret == 0) {printf("select³¬Ê±·µ»Ø£¬Ã»ÓÐÈκξä±ú״̬·¢Éú±ä»¯£¡");}
//Óоä±ú״̬·¢ÉúÁ˱仯
if(FD_ISSET(fd1, &readfds)) {
fd1ÓÐÊý¾Ý¿É¶Á;
fd1ÀïµÄÊý¾Ý±»¶Á³öÀ´;
}
if(FD_ISSET(fd2, &writefds)) {
fd2¿Éд;
fd2Àï·¢ËÍÊý¾Ý¸ø¶Ô·½;
}
}
/*----------------------ʾÒâ´úÂë½áÊø--------------------------------------------*/
[/CODE]
¾­³£Óõ½µÄ¼¸¸ö×Ô¶¨Ò庯Êý£º
1¡¢¿ªÆô¼àÌýµÄº¯Êý
[CODE]
/*----------------------Ô´´úÂë´úÂ뿪ʼ--------------------------------------------*/
int
OpenSCPServer(int port, int total, int sendbuflen, int recvbuflen, int blockORnot, int reuseORnot) {
/*************************¹ØÓÚ±¾º¯Êý************************************
*function_name: OpenSCPServer
*²ÎÊý˵Ã÷£ºportÕûÊýÐͼàÌý¶Ë¿ÚºÅ£¬totalÕûÊýÐͼàÌý¸öÊý£¬sendbuflenÕûÊýÐÍ·¢ËÍ»º³åÇø´óС
* recvbuflenÕûÊýÐͽÓÊÕ»º³åÇø´óС£¬blockORnotÕûÊýÐÍÊÇ·ñ×èÈû£¬reuseORnotÕûÊýÐÍÊÇ·ñ¶Ë¿ÚÖØÓÃ
*purpose: ÓÃÀ´½¨Á¢Ò»¸ötcp·þÎñ¶Ësocket
*tidied by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)
Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ
*date time:2006-07-05 20:00:00
*Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;
* µ«Çë×ñÑ­GPL
*Thanks to: Paul Sheer ¸ÐлPaul SheerÔÚselect_tutµÄmanÊÖ²áÀïÌṩÁËÕâ·ÝÔ´´úÂë
*Hope:Ï£ÍûÔ½À´Ô½¶àµÄÈ˹±Ï××Ô¼ºµÄÁ¦Á¿£¬Îª¿Æѧ¼¼Êõ·¢Õ¹³öÁ¦
*Note:ҪʹÓô˺¯ÊýÐèÒª×Ô¶¨ÒåÒ»¸öÈ«¾Ö±äÁ¿char errorMessage[1024];²¢°üº¬GetCurrentTime.hÍ·Îļþ
*********************************************************************/
int sockfd = 0, ret = 0, opt = 0, flags=1;
struct sockaddr_in laddr;

ret = sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(ret < 0) {
sprintf(errorMessage, "OpenTCPServer socket() error! return:%d, errno=%d, errortext:'%s' %s", ret, errno, strerror(errno), GetCurrentTime(0, 0));
return -1;
}

ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseORnot, sizeof(int));
if(ret < 0) {
sprintf(errorMessage, "OpenTCPServer setsockopt() reuse error! return:%d, errno=%d, errortext:'%s' %s", ret, errno, strerror(errno), GetCurrentTime(0, 0));
return -2;
}

ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvbuflen, sizeof(int));
if ( ret < 0) {
sprintf(errorMessage, "OpenTCPServer setsockopt() recvbuf error! return:%d, errno=%d, errortext:'%s' %s", ret, errno, strerror(errno), GetCurrentTime(0, 0));
return -3;
}

ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuflen, sizeof(int));
if (ret < 0) {
sprintf(errorMessage, "OpenTCPServer setsockopt() sendbuf error! return:%d, errno=%d, errortext:'%s' %s", ret, errno, strerror(errno), GetCurrentTime(0, 0));
return -4;
}

ioctl(sockfd,FIONBIO,&blockORnot);/*block or not*/

laddr.sin_family = PF_INET;
laddr.sin_port = htons(port);
laddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(laddr.sin_zero), 8);

ret = bind(sockfd, (struct sockaddr *)&laddr, sizeof(struct sockaddr));
if(ret < 0) {
sprintf(errorMessage, "OpenTCPServer bind() error! return:%d, errno=%d, errortext:'%s' %s", ret, errno, strerror(errno), GetCurrentTime(0, 0));
close(sockfd);
return -5;
}
ret = listen(sockfd, total);
if(ret < 0) {
sprintf(errorMessage, "OpenTCPServer listen() error! return:%d, errno=%d, errortext:'%s' %s", ret, errno, strerror(errno), GetCurrentTime(0, 0));
close(sockfd);
return -6;
}
sprintf(errorMessage, "OpenTCPServer opened on port.%d(%d) OK, socket(%d), buf(%d:%d)! %s", port, total, sockfd, sendbuflen, recvbuflen, GetCurrentTime(0, 0));
return sockfd;
}
/*----------------------Ô´´úÂë´úÂë½áÊø--------------------------------------------*/
[/CODE]
2¡¢Á¬½Ó·þÎñÆ÷µÄº¯Êý
[CODE]
/*----------------------Ô´´úÂë´úÂ뿪ʼ--------------------------------------------*/
int
ConnectSCPServer(char * serverip, int serverport, int blockORnot) {
/*************************¹ØÓÚ±¾º¯Êý************************************
*function_name: ConnectSCPServer
*²ÎÊý˵Ã÷£ºserverip·þÎñÆ÷IPµØÖ·»òÖ÷»úÃû£¬serverport·þÎñÆ÷¶Ë¿Ú£¬blockORnotÕûÊýÐÍÊÇ·ñ×èÈû
*purpose: ÓÃÀ´½¨Á¢Ò»¸ötcp¿Í»§¶Ësocket
*tidied by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)
Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ
*date time:2006-07-05 20:40:00
*Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;
* µ«Çë×ñÑ­GPL
*Thanks to: Paul Sheer ¸ÐлPaul SheerÔÚselect_tutµÄmanÊÖ²áÀïÌṩÁËÕâ·ÝÔ´´úÂë
*Hope:Ï£ÍûÔ½À´Ô½¶àµÄÈ˹±Ï××Ô¼ºµÄÁ¦Á¿£¬Îª¿Æѧ¼¼Êõ·¢Õ¹³öÁ¦
*Note:ҪʹÓô˺¯ÊýÐèÒª×Ô¶¨ÒåÒ»¸öÈ«¾Ö±äÁ¿char errorMessage[1024];²¢°üº¬×Ô¼º±àдµÄGetCurrentTime.hÍ·Îļþ
*********************************************************************/
int serversock = 0, ret = 0;
unsigned long addr;
struct sockaddr_in sin;
struct hostent *he;

if((he=gethostbyname(serverip))== 0) {
sprintf(errorMessage, "ConnectSCPServer IP address '%s' error! return:-1 %s", serverip, GetCurrentTime(0, 0));
return -1;
}

serversock = socket(PF_INET, SOCK_STREAM, 0);
if(serversock == -1) {
sprintf(errorMessage, "ConnectSCPServer socket() error! return:-2, errno=%d, errortext:'%s' %s", errno, strerror(errno), GetCurrentTime(0, 0));
return -2;
}

ioctl(serversock, FIONBIO, &blockORnot); //block or not

memset((char*)&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = PF_INET;
sin.sin_port = htons(serverport);
sin.sin_addr = *((struct in_addr *)he->h_addr);

ret = connect(serversock, (struct sockaddr *)&sin, sizeof(sin));

if(ret == -1) {
sprintf(errorMessage, "ConnectSCPServer connect() error! return:-3, errno=%d, errortext:'%s' %s", errno, strerror(errno), GetCurrentTime(0, 0));
close(serversock);
return -3;
}

return serversock;
}
/*----------------------Ô´´úÂë´úÂë½áÊø--------------------------------------------*/
[/CODE]
3¡¢·¢ËÍÊý¾Ýº¯ÊýSend
[CODE]
/*----------------------Ô´´úÂë´úÂ뿪ʼ--------------------------------------------*/
int
Send(int sock, char * buf, size_t size, int flag, int timeout) {
/*************************¹ØÓÚ±¾º¯Êý************************************
*function_name: Send
*²ÎÊý˵Ã÷£ºsockÕûÊýÐÍsocket£¬buf´ý·¢Ë͵ÄÄÚÈÝ£¬sizeÒª·¢Ë͵ĴóС£¬flag·¢ËÍÑ¡Ïtimeout³¬Ê±Ê±¼äÖµ
*purpose: ÓÃÀ´Í¨¹ýÒ»¸ösocketÔÚÖ¸¶¨Ê±¼äÄÚ·¢ËÍÊý¾Ý
*tidied by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)
Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ
*date time:2006-07-05 20:58:00
*Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;
* µ«Çë×ñÑ­GPL
*Thanks to: Paul Sheer ¸ÐлPaul SheerÔÚselect_tutµÄmanÊÖ²áÀïÌṩÁËÕâ·ÝÔ´´úÂë
*Hope:Ï£ÍûÔ½À´Ô½¶àµÄÈ˹±Ï××Ô¼ºµÄÁ¦Á¿£¬Îª¿Æѧ¼¼Êõ·¢Õ¹³öÁ¦
*Note:ҪʹÓô˺¯ÊýÐèÒª×Ô¶¨ÒåÒ»¸öÈ«¾Ö±äÁ¿char errorMessage[1024];²¢°üº¬×Ô¼º±àдµÄGetCurrentTime.hÍ·Îļþ
*********************************************************************/
int i = 0, ret = 0, intretry = 0;

struct timeval tival;
fd_set writefds;
int maxfds = 0;

tival.tv_sec = timeout;
tival.tv_usec = 0;

FD_ZERO(&writefds);

if(sock > 0) {
FD_SET(sock, &writefds);
maxfds=((sock > maxfds)?sock:maxfds);
}
else {
sprintf(errorMessage, "Send socket:%d error! return:-2 %s", sock, GetCurrentTime(0, 0));
return -2;
}

ret = select(maxfds + 1, NULL, &writefds, NULL, &tival);
if(ret <= 0) {
if(ret < 0) sprintf(errorMessage, "Send socket:%d select() error! return:%d, errno=%d, errortext:'%s' %s", sock, ret, errno, strerror(errno), GetCurrentTime(0, 0));
else sprintf(errorMessage, "Send socket:%d select timeout(%d)! %s", sock, timeout, GetCurrentTime(0, 0));
close(sock);
return -3;
}
if(!(FD_ISSET(sock, &writefds))) {
sprintf(errorMessage, "Send socket:%d not in writefds! %s", sock, GetCurrentTime(0, 0));
close(sock);
return -4;
}

while(i < size) {
ret = send(sock, buf + i, size - i, flag);
if(ret <= 0) {
sprintf(errorMessage, "Send socket:%d send() error! return:%d, errno=%d, errortext:'%s' %s", sock, ret, errno, strerror(errno), GetCurrentTime(0, 0));

if (EINTR == errno)
if(intretry < 10) {intretry++;continue;}
else sprintf(errorMessage, "Send socket:%d send() error!EINTR 10 times! %s", sock, GetCurrentTime(0, 0));

close(sock);
return -1;
}
else i += ret;
}
sprintf(errorMessage, "Send socket:%d send() OK! %d/%d bytes sent! %s", sock, i, size, GetCurrentTime(0, 0));
return i;
}
/*----------------------Ô´´úÂë´úÂë½áÊø--------------------------------------------*/
[/CODE]
4¡¢½ÓÊÕÊý¾Ýº¯ÊýRecv
[CODE]
/*----------------------Ô´´úÂë´úÂ뿪ʼ--------------------------------------------*/
int
Recv(int sock, char * buf, size_t size, int flag, int timeout) {
/*************************¹ØÓÚ±¾º¯Êý************************************
*function_name: Recv
*²ÎÊý˵Ã÷£ºsockÕûÊýÐÍsocket£¬buf½ÓÊÕÊý¾ÝµÄ»º³åÇø£¬sizeÒª½ÓÊÕÊý¾ÝµÄ´óС£¬flag½ÓÊÕÑ¡Ïtimeout³¬Ê±Ê±¼äÖµ
*purpose: ÓÃÀ´´ÓÒ»¸ösocketÔÚÖ¸¶¨Ê±¼äÄÚ¶ÁÈ¡Êý¾Ý
*tidied by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)
Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ
*date time:2006-07-05 21:10:00
*Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;
* µ«Çë×ñÑ­GPL
*Thanks to: Paul Sheer ¸ÐлPaul SheerÔÚselect_tutµÄmanÊÖ²áÀïÌṩÁËÕâ·ÝÔ´´úÂë
*Hope:Ï£ÍûÔ½À´Ô½¶àµÄÈ˹±Ï××Ô¼ºµÄÁ¦Á¿£¬Îª¿Æѧ¼¼Êõ·¢Õ¹³öÁ¦
*Note:ҪʹÓô˺¯ÊýÐèÒª×Ô¶¨ÒåÒ»¸öÈ«¾Ö±äÁ¿char errorMessage[1024];²¢°üº¬×Ô¼º±àдµÄGetCurrentTime.hÍ·Îļþ
*********************************************************************/
int i = 0, ret = 0, intretry = 0;

struct timeval tival;
fd_set readfds;
int maxfds = 0;

tival.tv_sec = timeout;
tival.tv_usec = 0;

FD_ZERO(&readfds);

if(sock > 0) {
FD_SET(sock, &readfds);
maxfds=((sock > maxfds)?sock:maxfds);
}
else {
sprintf(errorMessage, "Recv socket:%d error! return:-2 %s", sock, GetCurrentTime(0, 0));
return -2;
}

ret = select(maxfds + 1, &readfds, NULL, NULL, &tival);
if(ret <= 0) {
if(ret < 0) sprintf(errorMessage, "Recv socket:%d select() error! return:%d, errno=%d, errortext:'%s' %s", sock, ret, errno, strerror(errno), GetCurrentTime(0, 0));
else sprintf(errorMessage, "Recv socket:%d select timeout(%d)! %s", sock, timeout, GetCurrentTime(0, 0));
close(sock);
return -3;
}
if(!(FD_ISSET(sock, &readfds))) {
sprintf(errorMessage, "Recv socket:%d not in readfds! %s", sock, GetCurrentTime(0, 0));
close(sock);
return -4;
}
while(i < size) {
ret = recv(sock, buf + i, size - i, flag);
if(ret <= 0){
sprintf(errorMessage, "Recv socket:%d recv() error! return:%d, errno=%d, errortext:'%s' %s", sock, ret, errno, strerror(errno), GetCurrentTime(0, 0));
if(errno == EINTR)
if(intretry < 10) {intretry++;continue;}
else sprintf(errorMessage, "Recv socket:%d recv() error! EINTR 10 times! %s", sock, GetCurrentTime(0, 0));
close(sock);
return -1;
}
else i += ret;
}
sprintf(errorMessage, "Recv socket:%d recv() OK! %d/%d bytes received! %s", sock, i, size, GetCurrentTime(0, 0));
return i;
}
[/CODE]
×îºóÐèҪ˵Ã÷µÄÊÇ£ºÎÒÕâÀï½²µ½µÄÔ´³ÌÐò²¢²»ÄÜʵ¼ÊµØ×÷Ϊһ¸ö²úÆ·³ÌÐòÀ´Óã¬Êµ¼ÊÇé¿öÏ¿ÉÄÜ»áÓÐÆäËüÐí¶à¹¤×÷Òª×ö£¬±ÈÈç¿ÉÄÜÒª½¨Á¢¹²Ïí¶ÓÁÐÀ´´æ·Å socketÀï¶Áµ½µÄÏûÏ¢£¬Ò²¿ÉÄÜ°Ñ·¢ËÍÏûÏ¢ÏȽøÐÐÅŶÓÈ»ºóÔÙµ÷ÓÃSendº¯Êý¡£»¹ÓУ¬Èç¹û²»ÊÇÈ«Êý×Ö£¬ÔÚ·¢ËÍÇ°Ò»¶¨Òªhtonlת»»ÎªÍøÂç×Ö½ÚÐò£¬Í¬Àí½ÓÊÕµ½ºóÒ»¶¨ÒªÏÈntohlÓÉÍøÂç×Ö½ÚÐòת»»ÎªÖ÷»ú×Ö½ÚÐò£¬·ñÔò¶Ô·½·¢Ë͹ýÀ´µÄ0x00000001ÔÚÄãÕâÀï¿ÉÄÜÊÇ0x00010000£¬ÒòΪ¸ßµÍλ˳Ðò²»Í¬¡£
ÎÄÕÂÆÀÂÛ

¹²ÓÐ 9 ÌõÆÀÂÛ

  1. feng201310 ÓÚ 2014-05-19 14:43:36·¢±í:

    ÊÕ²ØÁË

  2. danylin ÓÚ 2013-08-21 11:45:37·¢±í:

    ºÃÌù£¬Ð»Ð»·ÖÏí£¡£¡£¡

  3. danylin ÓÚ 2013-08-21 11:45:32·¢±í:

    ºÃÌù£¬Ð»Ð»·ÖÏí£¡£¡£¡

  4. aslk12345 ÓÚ 2010-12-08 18:05:54·¢±í:

    xuexi

  5. yyxl ÓÚ 2010-12-08 15:51:22·¢±í:

    ÏÂÀ´¿´¿´£¬Â¥Ö÷ÐÁ¿àÁË£¡

  6. xue_1103 ÓÚ 2010-11-23 14:22:49·¢±í:

    ºÃ£¬ÊܽÌ

  7. nils ÓÚ 2006-07-12 23:49:55·¢±í:

    ¾ø¶Ô¾­µä£¡

  8. changlang ÓÚ 2006-07-07 10:12:10·¢±í:

    ºÃ¶«Î÷,ÊÕÏÂÁË

  9. zhoulifa ÓÚ 2006-07-06 22:57:08·¢±í:

    Linux 2.6ÄÚºËÖÐÌá¸ßÍøÂçI/OÐÔÄܵÄз½·¨epoll



    ÕýÈçÎÒ×òÌìÔÚ¡°Linuxϸ÷ÀàTCPÍøÂç·þÎñÆ÷µÄʵÏÖÔ´´úÂ롱(http://zhoulifa.bokee.com/5345930.html)Ò»ÎÄÖÐÌáµ½µÄÄÇÑù£¬I/O¶à·¸´Óü¼ÊõÔڱȽ϶àµÄTCPÍøÂç·þÎñÆ÷ÖÐÓÐʹÓ㬼´±È½Ï¶àµÄÓõ½selectº¯Êý¡£

    ¸Ðлchinaunix.netÉÏÅóÓÑsafedead(http://bbs.chinaunix.net/viewpro.php?uid=407631)ÌáÐÑ£¬ÎÒ½ñÌì×ÐϸÑо¿ÁËһϣ¬Ö¤ÊµÁËÔÚ2.6ÄÚºËÖеÄеÄI/O¼¼Êõepoll¡£



    1¡¢ÎªÊ²Ã´selectÊÇÂäºóµÄ£¿

    Ê×ÏÈ£¬ÔÚLinuxÄÚºËÖУ¬selectËùÓõ½µÄFD_SETÊÇÓÐÏ޵ģ¬¼´ÄÚºËÖÐÓиö²ÎÊý__FD_SETSIZE¶¨ÒåÁËÿ¸öFD_SETµÄ¾ä±ú¸öÊý£¬ÔÚÎÒÓõÄ2.6.15-25-386ÄÚºËÖУ¬¸ÃÖµÊÇ1024£¬ËÑË÷ÄÚºËÔ´´úÂëµÃµ½£º

    include/linux/posix_types.h:#define __FD_SETSIZE 1024

    Ò²¾ÍÊÇ˵£¬Èç¹ûÏëҪͬʱ¼ì²â1025¸ö¾ä±úµÄ¿É¶Á״̬ÊDz»¿ÉÄÜÓÃselectʵÏֵġ£»òÕßͬʱ¼ì²â1025¸ö¾ä±úµÄ¿Éд״̬ҲÊDz»¿ÉÄܵġ£

    Æä´Î£¬ÄÚºËÖÐʵÏÖselectÊÇÓÃÂÖѯ·½·¨£¬¼´Ã¿´Î¼ì²â¶¼»á±éÀúËùÓÐFD_SETÖеľä±ú£¬ÏÔÈ»£¬selectº¯ÊýÖ´ÐÐʱ¼äÓëFD_SETÖеľä±ú¸öÊýÓÐÒ»¸ö±ÈÀý¹Øϵ£¬¼´selectÒª¼ì²âµÄ¾ä±úÊýÔ½¶à¾Í»áÔ½·Ñʱ¡£

    µ±È»£¬ÔÚÇ°ÎÄÖÐÎÒ²¢Ã»ÓÐÌá¼°poll·½·¨£¬ÊÂʵÉÏÓÃselectµÄÅóÓÑÒ»¶¨Ò²ÊÔ¹ýpoll£¬ÎÒ¸öÈ˾õµÃselectºÍpoll´óͬСÒ죬¸öÈËÆ«ºÃÓÚÓÃselect¶øÒÑ¡£



    /************¹ØÓÚ±¾Îĵµ********************************************

    *filename: Linux 2.6ÄÚºËÖÐÌá¸ßÍøÂçI/OÐÔÄܵÄз½·¨epoll

    *purpose: ²¹³ä¡°Linuxϸ÷ÀàTCPÍøÂç·þÎñÆ÷µÄʵÏÖÔ´´úÂ롱һÎĵIJ»×ãÖ®´¦

    *wrote by: zhoulifa(zhoulifa@163.com) ÖÜÁ¢·¢(http://zhoulifa.bokee.com)

    Linux°®ºÃÕß Linux֪ʶ´«²¥Õß SOHO×å ¿ª·¢Õß ×îÉó¤CÓïÑÔ

    *date time:2006-07-06 22:30:00

    *Note: ÈκÎÈË¿ÉÒÔÈÎÒ⸴ÖÆ´úÂë²¢ÔËÓÃÕâЩÎĵµ£¬µ±È»°üÀ¨ÄãµÄÉÌÒµÓÃ;

    * µ«Çë×ñÑ­GPL

    *Hope:Ï£ÍûÔ½À´Ô½¶àµÄÈ˹±Ï××Ô¼ºµÄÁ¦Á¿£¬Îª¿Æѧ¼¼Êõ·¢Õ¹³öÁ¦

    *********************************************************************/



    2¡¢2.6ÄÚºËÖÐÌá¸ßI/OÐÔÄܵÄз½·¨epoll



    epollÊÇʲô£¿°´ÕÕmanÊÖ²áµÄ˵·¨£ºÊÇΪ´¦Àí´óÅúÁ¿¾ä±ú¶ø×÷Á˸ĽøµÄpoll¡£ÒªÊ¹ÓÃepollÖ»ÐèÒªÕâÈý¸öϵͳµ÷Óãºepoll_create(2)£¬ epoll_ctl(2)£¬ epoll_wait(2)¡£

    µ±È»£¬Õâ²»ÊÇ2.6Äں˲ÅÓеģ¬ËüÊÇÔÚ2.5.44ÄÚºËÖб»Òý½øµÄ(epoll(4) is a new API introduced in Linux kernel 2.5.44)



    ÒÔÏÂÎÄÕÂת×ÔëøêŵÄWeb Log http://mechgouki.spaces.msn.com/blog/PersonalSpace.aspx

    ÒýÓÃ:


    /*********************************ÒýÓÿªÊ¼******************************/

    Linux2.6ÄÚºËepoll½éÉÜ---ÎÒµÄblog 2005/3/30



    [×÷Õß]£ºëøêÅ,2005/3/30,0.1°æ±¾



    [°æȨÉùÃ÷]£º´ËÎĵµ×ñÑ­GNU×ÔÓÉÎĵµÐí¿ÉÖ¤(GNU Free Documentation License).ÈκÎÈË¿ÉÒÔ×ÔÓɸ´ÖÆ,·Ö·¢,ÐÞ¸Ä,²»¹ýÈç¹û·½±ã,Çë×¢Ã÷³ö´¦ºÍ×÷Õß:)



    (1)µ¼ÑÔ£º



    Ê×ÏÈ£¬ÎÒÇ¿ÁÒ½¨Òé´ó¼ÒÔĶÁRichard StevensÖø×÷¡¶TCP/IP Illustracted Volume 1,2,3¡·ºÍ¡¶UNIX Network Programming Volume 1,2¡·¡£ËäÈ»ËûÀ뿪ÎÒÃÇ´ó¼ÒÒѾ­5Äê¶àÁË£¬µ«ÊÇËûµÄÊéÒÀÈ»ÊǽøÈëÍøÂç±à³ÌµÄ×îÖ±½ÓµÄµÀ·¡£ÆäÖеÄ3¾íµÄ¡¶TCP/IP Illustracted¡·¾í1ÊDZضÁ£­Èç¹ûÄã²»Á˽âtcpЭÒé¸÷¸öÑ¡ÏîµÄÏêϸ¶¨Ò壬Äã¾ÍʧȥÁËÓÅ»¯³ÌÐòÖØÒªµÄÒ»¸öÊֶΡ£¾í2,3¿ÉÒÔÑ¡¶Áһϡ£±ÈÈç¾í2 ½²½âµÄÊÇ4.4BSDÄÚºËTCP/IPЭÒéջʵÏÖ----Õâ¸ö°æ±¾µÄЭÒéÕ»¼¸ºõÓ°ÏìÁËÏÖÔÚËùÓеÄÖ÷Á÷os£¬µ«ÊÇÒòΪÄê´ú¾ÃÔ¶£¬ÄÚÈݲ»Ò»¶¨ÄÇôvogue. ÔÚÕâÀïÎÒ¶àÍƼöÒ»±¾¡¶The Linux Networking Architecture--Design and Implementation of Network Protocols in the Linux Kernel¡·£¬ÒÔ2.4Äں˽²½âLinux TCP/IPʵÏÖ£¬Ï൱²»´í.×÷Ϊһ¸öÏÖʵÊÀ½çÖеÄʵÏÖ£¬ºÜ¶àʱºòÄã±ØÐë×÷ºÜ¶àȨºâ£¬Õâʱºò²Î¿¼Ò»¸ö¾Ã¾­¿¼ÑéµÄϵͳ¸üÓÐʵ¼ÊÒâÒå¡£¾Ù¸öÀý×Ó,linuxÄÚºËÖÐsk_buff½á¹¹ÎªÁË×·ÇóËٶȺͰ²È«£¬ÎþÉüÁ˲¿·ÖÄڴ棬ËùÒÔÔÚ·¢ËÍTCP°üµÄʱºò£¬ÎÞÂÛÓ¦ÓòãÊý¾Ý¶à´ó,sk_buff×îСҲÓÐ272µÄ×Ö½Ú.



    Æäʵ¶ÔÓÚsocketÓ¦Óòã³ÌÐòÀ´Ëµ£¬¡¶UNIX Network Programming Volume 1¡·ÒâÒå¸ü´óÒ»µã.2003ÄêµÄʱºò£¬Õâ±¾Êé³öÁË×îеĵÚ3°æ±¾£¬²»¹ýÖ÷Òª»¹ÊÇÐÞ¶©µÚ2°æ±¾¡£ÆäÖеÚ6Õ¡¶I/O Multiplexing¡·ÊÇ×îÖØÒªµÄ¡£Stevens¸ø³öÁËÍøÂçIOµÄ»ù±¾Ä£ÐÍ¡£ÔÚÕâÀï×îÖØÒªµÄĪ¹ýÓÚselectÄ£ÐͺÍAsynchronous I/OÄ£ÐÍ.´ÓÀíÂÛÉÏ˵£¬AIOËƺõÊÇ×î¸ßЧµÄ£¬ÄãµÄIO²Ù×÷¿ÉÒÔÁ¢¼´·µ»Ø£¬È»ºóµÈ´ýos¸æËßÄãIO²Ù×÷Íê³É¡£µ«ÊÇÒ»Ö±ÒÔÀ´£¬ÈçºÎʵÏÖ¾ÍûÓÐÒ»¸öÍêÃÀµÄ·½°¸¡£×îÖøÃûµÄwindowsÍê³É¶Ë¿ÚʵÏÖµÄAIO,ʵ¼ÊÉÏÒ²ÊÇÄÚ²¿ÓÃÏ̳߳ØʵÏֵİÕÁË£¬×îºóµÄ½á¹ûÊÇIOÓиöÏ̳߳أ¬ÄãÓ¦ÓÃÒ²ÐèÒªÒ»¸öÏ̳߳Ø...... ºÜ¶àÎĵµÆäʵÒѾ­Ö¸³öÁËÕâ´øÀ´µÄÏß³Ìcontext-switch´øÀ´µÄ´ú¼Û¡£



    ÔÚlinux ƽ̨ÉÏ£¬¹ØÓÚÍøÂçAIOÒ»Ö±ÊǸĶ¯×î¶àµÄµØ·½£¬2.4µÄÄê´ú¾ÍÓкܶàAIOÄÚºËpatch,×îÖøÃûµÄÓ¦¸ÃËãÊÇSGIÄǸö¡£µ«ÊÇÒ»Ö±µ½2.6Äں˷¢²¼£¬ÍøÂçÄ£¿éµÄAIOһֱûÓнøÈëÎȶ¨Äں˰汾(´ó²¿·Ö¶¼ÊÇʹÓÃÓû§Ïß³ÌÄ£Äâ·½·¨£¬ÔÚʹÓÃÁËNPTLµÄlinuxÉÏÃæÆäʵºÍwindowsµÄÍê³É¶Ë¿Ú»ù±¾Éϲ¶àÁË)¡£2.6ÄÚºËËùÖ§³ÖµÄAIOÌØÖ¸´ÅÅ̵ÄAIO---Ö§³Öio_submit(),io_getevents()ÒÔ¼°¶ÔDirect IOµÄÖ§³Ö(¾ÍÊÇÈƹýVFSϵͳbufferÖ±½ÓдӲÅÌ£¬¶ÔÓÚÁ÷·þÎñÆ÷ÔÚÄÚ´æƽÎÈÐÔÉÏÓÐÏ൱°ïÖú)¡£



    ËùÒÔ£¬Ê£ÏµÄselectÄ£ÐÍ»ù±¾ÉϾÍÊÇÎÒÃÇÔÚlinuxÉÏÃæµÄΨһѡÔñ£¬Æäʵ£¬Èç¹û¼ÓÉÏno-block socketµÄÅäÖ㬿ÉÒÔÍê³ÉÒ»¸ö"α"AIOµÄʵÏÖ£¬Ö»²»¹ýÍƶ¯Á¦ÔÚÓÚÄã¶ø²»ÊÇos¶øÒÑ¡£²»¹ý´«Í³µÄselect/pollº¯ÊýÓÐ×ÅһЩÎÞ·¨ÈÌÊܵÄȱµã£¬ËùÒԸĽøÒ»Ö±ÊÇ2.4-2.5¿ª·¢°æ±¾Äں˵ÄÈÎÎñ£¬°üÀ¨/dev/poll£¬realtime signalµÈµÈ¡£×îÖÕ£¬Davide Libenzi¿ª·¢µÄepoll½øÈë2.6Äں˳ÉΪÕýʽµÄ½â¾ö·½°¸



    (2)epollµÄÓŵã



    <1>Ö§³ÖÒ»¸ö½ø³Ì´ò¿ª´óÊýÄ¿µÄsocketÃèÊö·û(FD)



    select ×î²»ÄÜÈÌÊܵÄÊÇÒ»¸ö½ø³ÌËù´ò¿ªµÄFDÊÇÓÐÒ»¶¨ÏÞÖƵģ¬ÓÉFD_SETSIZEÉèÖã¬Ä¬ÈÏÖµÊÇ2048¡£¶ÔÓÚÄÇЩÐèÒªÖ§³ÖµÄÉÏÍòÁ¬½ÓÊýÄ¿µÄIM·þÎñÆ÷À´ËµÏÔȻ̫ÉÙÁË¡£ÕâʱºòÄãÒ»ÊÇ¿ÉÒÔÑ¡ÔñÐÞ¸ÄÕâ¸öºêÈ»ºóÖØбàÒëÄںˣ¬²»¹ý×ÊÁÏҲͬʱָ³öÕâÑù»á´øÀ´ÍøÂçЧÂʵÄϽµ£¬¶þÊÇ¿ÉÒÔÑ¡Ôñ¶à½ø³ÌµÄ½â¾ö·½°¸(´«Í³µÄApache·½°¸)£¬²»¹ýËäÈ»linuxÉÏÃæ´´½¨½ø³ÌµÄ´ú¼Û±È½ÏС£¬µ«ÈÔ¾ÉÊDz»¿ÉºöÊӵģ¬¼ÓÉϽø³Ì¼äÊý¾Ýͬ²½Ô¶±È²»ÉÏÏ̼߳äͬ²½µÄ¸ßЧ£¬ËùÒÔÒ²²»ÊÇÒ»ÖÖÍêÃÀµÄ·½°¸¡£²»¹ý epollÔòûÓÐÕâ¸öÏÞÖÆ£¬ËüËùÖ§³ÖµÄFDÉÏÏÞÊÇ×î´ó¿ÉÒÔ´ò¿ªÎļþµÄÊýÄ¿£¬Õâ¸öÊý×ÖÒ»°ãÔ¶´óÓÚ2048,¾Ù¸öÀý×Ó,ÔÚ1GBÄÚ´æµÄ»úÆ÷ÉÏ´óÔ¼ÊÇ10Íò×óÓÒ£¬¾ßÌåÊýÄ¿¿ÉÒÔcat /proc/sys/fs/file-max²ì¿´,Ò»°ãÀ´ËµÕâ¸öÊýÄ¿ºÍϵͳÄÚ´æ¹ØϵºÜ´ó¡£



    <2>IOЧÂʲ»ËæFDÊýÄ¿Ôö¼Ó¶øÏßÐÔϽµ



    ´«Í³µÄselect/pollÁíÒ»¸öÖÂÃüÈõµã¾ÍÊǵ±ÄãÓµÓÐÒ»¸öºÜ´óµÄsocket¼¯ºÏ£¬²»¹ýÓÉÓÚÍøÂçÑÓʱ£¬ÈÎһʱ¼äÖ»Óв¿·ÖµÄsocketÊÇ"»îÔ¾"µÄ£¬µ«ÊÇselect/pollÿ´Îµ÷Óö¼»áÏßÐÔɨÃèÈ«²¿µÄ¼¯ºÏ£¬µ¼ÖÂЧÂʳÊÏÖÏßÐÔϽµ¡£µ«ÊÇepoll²»´æÔÚÕâ¸öÎÊÌ⣬ËüÖ»»á¶Ô"»îÔ¾"µÄsocket½øÐвÙ×÷---ÕâÊÇÒòΪÔÚÄÚºËʵÏÖÖÐepollÊǸù¾Ýÿ¸öfdÉÏÃæµÄcallbackº¯ÊýʵÏֵġ£ÄÇô£¬Ö»ÓÐ"»îÔ¾"µÄsocket²Å»áÖ÷¶¯µÄÈ¥µ÷Óà callbackº¯Êý£¬ÆäËûidle״̬socketÔò²»»á£¬ÔÚÕâµãÉÏ£¬epollʵÏÖÁËÒ»¸ö"α"AIO£¬ÒòΪÕâʱºòÍƶ¯Á¦ÔÚosÄںˡ£ÔÚһЩ benchmarkÖУ¬Èç¹ûËùÓеÄsocket»ù±¾É϶¼ÊÇ»îÔ¾µÄ---±ÈÈçÒ»¸ö¸ßËÙLAN»·¾³£¬epoll²¢²»±Èselect/pollÓÐʲôЧÂÊ£¬Ïà·´£¬Èç¹û¹ý¶àʹÓÃepoll_ctl,ЧÂÊÏà±È»¹ÓÐÉÔ΢µÄϽµ¡£µ«ÊÇÒ»µ©Ê¹ÓÃidle connectionsÄ£ÄâWAN»·¾³,epollµÄЧÂʾÍÔ¶ÔÚselect/pollÖ®ÉÏÁË¡£



    <3>ʹÓÃmmap¼ÓËÙÄÚºËÓëÓû§¿Õ¼äµÄÏûÏ¢´«µÝ¡£



    Õâµãʵ¼ÊÉÏÉæ¼°µ½epollµÄ¾ßÌåʵÏÖÁË¡£ÎÞÂÛÊÇselect,poll»¹ÊÇepoll¶¼ÐèÒªÄں˰ÑFDÏûϢ֪ͨ¸øÓû§¿Õ¼ä£¬ÈçºÎ±ÜÃâ²»±ØÒªµÄÄڴ濽±´¾ÍºÜÖØÒª£¬ÔÚÕâµãÉÏ£¬epollÊÇͨ¹ýÄÚºËÓÚÓû§¿Õ¼ämmapͬһ¿éÄÚ´æʵÏֵġ£¶øÈç¹ûÄãÏëÎÒÒ»Ñù´Ó2.5Äں˾͹Ø×¢epollµÄ»°£¬Ò»¶¨²»»áÍü¼ÇÊÖ¹¤ mmapÕâÒ»²½µÄ¡£



    <4>ÄÚºË΢µ÷



    ÕâÒ»µãÆäʵ²»ËãepollµÄÓŵãÁË£¬¶øÊÇÕû¸ölinuxƽ̨µÄÓŵ㡣ҲÐíÄã¿ÉÒÔ»³ÒÉlinuxƽ̨£¬µ«ÊÇÄãÎÞ·¨»Ø±Ülinuxƽ̨¸³ÓèÄã΢µ÷Äں˵ÄÄÜÁ¦¡£±ÈÈ磬ÄÚºËTCP/IPЭÒéջʹÓÃÄÚ´æ³Ø¹ÜÀísk_buff½á¹¹£¬ÄÇô¿ÉÒÔÔÚÔËÐÐʱÆÚ¶¯Ì¬µ÷ÕûÕâ¸öÄÚ´æpool(skb_head_pool)µÄ´óС--- ͨ¹ýecho XXXX>/proc/sys/net/core/hot_list_lengthÍê³É¡£ÔÙ±ÈÈçlistenº¯ÊýµÄµÚ2¸ö²ÎÊý(TCPÍê³É3´ÎÎÕÊÖµÄÊý¾Ý°ü¶ÓÁ㤶È)£¬Ò²¿ÉÒÔ¸ù¾ÝÄãƽ̨ÄÚ´æ´óС¶¯Ì¬µ÷Õû¡£¸üÉõÖÁÔÚÒ»¸öÊý¾Ý°üÃæÊýÄ¿¾Þ´óµ«Í¬Ê±Ã¿¸öÊý¾Ý°ü±¾Éí´óСȴºÜСµÄÌØÊâϵͳÉϳ¢ÊÔ×îеÄNAPIÍø¿¨Çý¶¯¼Ü¹¹¡£



    (3)epollµÄʹÓÃ



    ÁîÈ˸ßÐ˵ÄÊÇ£¬2.6Äں˵Äepoll±ÈÆä2.5¿ª·¢°æ±¾µÄ/dev/epoll¼ò½àÁËÐí¶à£¬ËùÒÔ£¬´ó²¿·ÖÇé¿öÏ£¬Ç¿´óµÄ¶«Î÷ÍùÍùÊǼòµ¥µÄ¡£Î¨Ò»ÓеãÂé·³ÊÇepollÓÐ2ÖÖ¹¤×÷·½Ê½:LTºÍET¡£



    LT(level triggered)ÊÇȱʡµÄ¹¤×÷·½Ê½£¬²¢ÇÒͬʱ֧³ÖblockºÍno-block socket.ÔÚÕâÖÖ×ö·¨ÖУ¬Äں˸æËßÄãÒ»¸öÎļþÃèÊö·ûÊÇ·ñ¾ÍÐ÷ÁË£¬È»ºóÄã¿ÉÒÔ¶ÔÕâ¸ö¾ÍÐ÷µÄfd½øÐÐIO²Ù×÷¡£Èç¹ûÄã²»×÷ÈκβÙ×÷£¬Äں˻¹ÊÇ»á¼ÌÐø֪ͨÄãµÄ£¬ËùÒÔ£¬ÕâÖÖģʽ±à³Ì³ö´íÎó¿ÉÄÜÐÔҪСһµã¡£´«Í³µÄselect/poll¶¼ÊÇÕâÖÖÄ£Ð͵Ĵú±í£®



    ET (edge-triggered)ÊǸßËÙ¹¤×÷·½Ê½£¬Ö»Ö§³Öno-block socket¡£ÔÚÕâÖÖģʽÏ£¬µ±ÃèÊö·û´Óδ¾ÍÐ÷±äΪ¾ÍÐ÷ʱ£¬ÄÚºËͨ¹ýepoll¸æËßÄ㡣ȻºóËü»á¼ÙÉèÄãÖªµÀÎļþÃèÊö·ûÒѾ­¾ÍÐ÷£¬²¢ÇÒ²»»áÔÙΪÄǸöÎļþÃèÊö·û·¢Ë͸ü¶àµÄ¾ÍÐ÷֪ͨ£¬Ö±µ½Äã×öÁËijЩ²Ù×÷µ¼ÖÂÄǸöÎļþÃèÊö·û²»ÔÙΪ¾ÍÐ÷״̬ÁË(±ÈÈ磬ÄãÔÚ·¢ËÍ£¬½ÓÊÕ»òÕß½ÓÊÕÇëÇ󣬻òÕß·¢ËͽÓÊÕµÄÊý¾ÝÉÙÓÚÒ»¶¨Á¿Ê±µ¼ÖÂÁËÒ»¸öEWOULDBLOCK ´íÎ󣩡£µ«ÊÇÇë×¢Ò⣬Èç¹ûÒ»Ö±²»¶ÔÕâ¸öfd×÷IO²Ù×÷(´Ó¶øµ¼ÖÂËüÔٴαä³Éδ¾ÍÐ÷)£¬Äں˲»»á·¢Ë͸ü¶àµÄ֪ͨ(only once),²»¹ýÔÚTCPЭÒéÖУ¬ETģʽµÄ¼ÓËÙЧÓÃÈÔÐèÒª¸ü¶àµÄbenchmarkÈ·ÈÏ¡£



    epollÖ»ÓÐepoll_create,epoll_ctl,epoll_wait 3¸öϵͳµ÷Ó㬾ßÌåÓ÷¨Çë²Î¿¼http://www.xmailserver.org/linux-patches/nio-improve.html £¬

    ÔÚhttp://www.kegel.com/rn/Ò²ÓÐÒ»¸öÍêÕûµÄÀý×Ó£¬´ó¼ÒÒ»¿´¾ÍÖªµÀÈçºÎʹÓÃÁË



    (4)Leader/followerģʽÏß³ÌpoolʵÏÖ£¬ÒÔ¼°ºÍepollµÄÅäºÏ



    .....δÍê³É£¬Ö÷ÒªÊÇÒª±ÜÃâ¹ý¶àµÄepoll_ctlµ÷ÓÃ,ÒÔ¼°³¢ÊÔʹÓÃEPOLLONESHOT¼ÓËÙ......



    (5)benchmark



    .......δÍê³É

    /*********************************ÒýÓýáÊø******************************/



    3¡¢epollµÄʹÓ÷½·¨

    ÕâÊÇepollµÄmanÊÖ²áÌṩµÄÒ»¸öÀý×Ó£¬Õâ¶Î´úÂë¼ÙÉèÒ»¸ö·Ç×èÈûµÄsocket¼àÌýlistener±»½¨Á¢²¢ÇÒÒ»¸öepoll¾ä±úkdpfdÒѾ­ÌáÇ°ÓÃepoll_create½¨Á¢ÁË£º

    [CODE]
    struct epoll_event ev, *events;



    for(;;) {

    nfds = epoll_wait(kdpfd, events, maxevents, -1);/*wait for an I/O event. All notes here added by zhoulifa(http://zhoulifa.bokee.com) on 2006-7-6 22:10:00*/



    for(n = 0; n < nfds; ++n) {

    if(events[n].data.fd == listener) {/*if listen socket has an I/O, accept the new connect*/

    client = accept(listener, (struct sockaddr *) &local,

    &addrlen);

    if(client < 0){

    perror("accept");

    continue;

    }

    setnonblocking(client);

    ev.events = EPOLLIN | EPOLLET;/*EPOLLIN-available for read*/

    ev.data.fd = client;

    if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {/*add the new socket into the epoll file descriptors*/

    fprintf(stderr, "epoll set insertion error: fd=%d\n",

    client);

    return -1;

    }

    }

    else

    do_use_fd(events[n].data.fd);/*read from a socket which has data come*/

    }

    }

    [/CODE]
    4¡¢epollʹÓ÷½·¨Ê¾Òâ´úÂë

    ÒÔÏ´úÂëÓÉchinaunix.netÉÏBBSÓû§safedead(http://bbs.chinaunix.net/viewpro.php?uid=407631)Ìṩ£º



    [CODE]
    static int s_epfd;//epollÃèÊö×Ö



    {//³õʼ»¯epoll

    struct epoll_event ev;



    //ÉèÖÃepoll

    s_epfd = epoll_create(65535);



    {//Õâ¸ö¹ý³Ì¿ÉÒÔÑ­»·ÒÔ±ã¼ÓÈë¶à¸öLISTENÌ×½Ó×Ö½øÈëepollʼþ¼¯ºÏ

    //·þÎñÆ÷¼àÌý´´½¨

    rc = listen();//listen²ÎÊýÕâÀïÊ¡ÂÔ



    //¼ÓÈëepollʼþ¼¯ºÏ

    ev.events = EPOLLIN;

    ev.data.fd = rc;

    if (epoll_ctl(s_epfd, EPOLL_CTL_ADD, rc, &ev) < 0) {

    fprintf(stderr, "epoll set insertion error: fd=%d", rc);

    return(-1);

    }

    }

    }



    {//epollʼþ´¦Àí

    int i, nfds, sock_new;

    struct epoll_event events[16384];

    for( ; ; ) {

    //µÈ´ýepollʼþ

    nfds = epoll_wait(s_epfd, events, 16384, -1);

    //´¦Àíepollʼþ

    for(i = 0; i < nfds; i++) {

    //events[i].data.fdÊÇepollʼþÖе¯³öµÄÌ×½Ó×Ö

    //½ÓÊÕÁ¬½Ó

    sock_new = accept(events[i].data.fd);//acceptÆäËü²ÎÊýÕâÀïÊ¡ÂÔÁË

    if(0 > sock_new) {

    fprintf(stderr, "½ÓÊÕ¿Í»§¶ËÁ¬½Óʧ°Ü\n");

    continue;

    }

    }

    }

    }

    [/CODE]
    ¶ÔÕÕsafedeadºÍÇ°ÃæµÄÒ»·Ý´úÂ룬ÎÒÏë´ó¼ÒÒ»¶¨ÊÇÃ÷°×Á˵ġ£



    5¡¢²Î¿¼Îĵµ

    Improving (network) I/O performance ...

    http://www.xmailserver.org/linux-patches/nio-improve.html