Ê×ÏÈ£¬Ñ»·ÍøÂç·þÎñÆ÷±à³ÌʵÏֵ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£¬ÒòΪ¸ßµÍλ˳Ðò²»Í¬¡£
feng201310 ÓÚ 2014-05-19 14:43:36·¢±í:
ÊÕ²ØÁË
danylin ÓÚ 2013-08-21 11:45:37·¢±í:
ºÃÌù£¬Ð»Ð»·ÖÏí£¡£¡£¡
danylin ÓÚ 2013-08-21 11:45:32·¢±í:
ºÃÌù£¬Ð»Ð»·ÖÏí£¡£¡£¡
aslk12345 ÓÚ 2010-12-08 18:05:54·¢±í:
xuexi
yyxl ÓÚ 2010-12-08 15:51:22·¢±í:
ÏÂÀ´¿´¿´£¬Â¥Ö÷ÐÁ¿àÁË£¡
xue_1103 ÓÚ 2010-11-23 14:22:49·¢±í:
ºÃ£¬ÊܽÌ
nils ÓÚ 2006-07-12 23:49:55·¢±í:
¾ø¶Ô¾µä£¡
changlang ÓÚ 2006-07-07 10:12:10·¢±í:
ºÃ¶«Î÷,ÊÕÏÂÁË
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
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