锘??xml version="1.0" encoding="utf-8" standalone="yes"?> Linux 涓嬮楦戒紶涔﹁璁″疄鐜?span lang="EN-US"> 1.緋葷粺鍔熻兘 鏍規嵁椋為附浼犱功鍗忚鍦?span lang="EN-US"> linux 涓嬪疄鐜伴楦戒紶杈撶▼搴?span lang="EN-US">,騫朵笖涓?span lang="EN-US"> windows 涓嬮楦藉吋瀹廣傚叿浣撳姛鑳芥ā鍧楀寘鎷敤鎴蜂笂綰?span lang="EN-US">,涓嬬嚎,鍒鋒柊鏌ョ湅鍦ㄧ嚎鐢ㄦ埛,鏀跺彂娑堟伅,浼犻佹枃浠?span lang="EN-US">/鏂囦歡澶瑰姛鑳芥ā鍧椼?span lang="EN-US"> 2.鍏蜂綋瀹炵幇 2.1 鍏抽敭鏁版嵁緇撴瀯 /*鍛戒護鐨勭粨鏋?span lang="EN-US">*/ typedef struct _command { int version;/*鍛戒護鐨勭増鏈?span lang="EN-US">*/ int seq;/*鍖呯紪鍙?span lang="EN-US">*/ char
srcName[100];/*鍙戦佽呭鍚?span lang="EN-US">*/ char
srcHost[100];/*鍙戦佽呬富鏈哄悕*/ int flag;/*鍛戒護*/ char
addtion[100];/*闄勫姞瀛楁*/ }command; /*鍦ㄧ嚎鐢ㄦ埛淇℃伅*/ typedef struct _userInfo { char
name[MAXLINE]; /*濮撳悕*/ char
host[MAXLINE]; /*涓繪満鍚?span lang="EN-US">*/ char
group[MAXLINE]; /*鎵鍦ㄧ殑緇勫悕*/ struct
sockaddr_in addr; /*鍦板潃淇℃伅*/ struct
_userInfo next; /*閾捐〃涓笅涓涓?span lang="EN-US">*/ }userInfo; /*鍦ㄧ嚎鐢ㄦ埛鍒楄〃*/ typedef struct _uList { userInfo
*userListHead; /*閾捐〃澶?span lang="EN-US">*/ userInfo
userListTail; /*閾捐〃灝?span lang="EN-US">*/ }uList; /*娑堟伅闃熷垪*/ typedef struct _mesList { command
*mesHead; command
*mesTail; }mesList; 2.2 紼嬪簭涓昏緇撴瀯 鏈▼搴忎富瑕侀噰鐢ㄥ綰跨▼緇撴瀯,鍒嗕負 receive(鎺ユ敹娑堟伅), process(澶勭悊鏀跺埌鐨勬秷鎭?span lang="EN-US">), sendData(鍙戦佹枃浠?span lang="EN-US">) 涓変釜瀛愮嚎紼嬨傜嚎紼嬮棿閫氫俊浜掓枼閿佷笌 Posix 淇″彿閲忚繘琛岄氫俊銆?span lang="EN-US"> 2.3 鍑芥暟鎺ュ彛 (1) /*浠庢枃浠舵弿榪扮fd涓鍙?span lang="EN-US">count涓瓧絎﹀瓨鍏?span lang="EN-US">buf涓?span lang="EN-US">*/ ssize_t
readn(int fd,void *buf,size_t count)錛?span lang="EN-US"> (2) /*灝?span lang="EN-US">buf鎵鎸囧悜鐨勫瓨鍌ㄥ尯涓殑len涓瓧絎﹀惛鍏ユ枃浠舵弿榪扮fd涓?span lang="EN-US">*/ ssize_t
writen(int fd,char *buf,int len); (3) /*鐢ㄤ簬瀛楃涓茶漿鎹?span lang="EN-US">,緗戠粶浼犺緭涓敤gb2312緙栫爜錛?span lang="EN-US">linux涓?span lang="EN-US">gtk鐢?span lang="EN-US">utf-8緙栫爜錛岄渶瑕佽繘琛岃漿鎹?span lang="EN-US">*/ int
code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char
*outbuf,int outlen); (4) /*鍦ㄧ敤鎴烽摼琛ㄤ腑鍔犲叆鏂扮敤鎴蜂俊鎭紝鍔犲叆鎴愬姛榪斿洖1錛屽惁鍒欒繑鍥?span lang="EN-US">0,浣跨敤userInfoMutex榪涜綰跨▼闂撮氫俊鎺у埗*/ int
pushBack(uList *list,userInfo user); (5) /*鍦ㄧ敤鎴烽摼琛ㄤ腑鍒犻櫎鎸囧畾鍦板潃淇℃伅鐨勭敤鎴鳳紝鍒犻櫎鎴愬姛鍚庤繑鍥?span lang="EN-US">1錛屽惁鍒欒繑鍥?span lang="EN-US">0錛屼嬌鐢?span lang="EN-US">userInfoMutex榪涜綰跨▼闂存帶鍒?span lang="EN-US">*/ int
delUser(uList *list, struct sockaddr_in addr); (6) /*鍒ゆ柇璇ョ敤鎴鋒槸鍚﹀凡緇忓瓨鍦紝宸茬粡瀛樺湪鍒欒繑鍥?span lang="EN-US">1錛屽惁鍒欒繑鍥?span lang="EN-US">0,浣跨敤userInfoMutex榪涜綰跨▼闂存帶鍒?span lang="EN-US">*/ int isExist(uList *list,struct sockaddr_in addr); (7)娓呯┖鐢ㄦ埛閾捐〃錛岄噴鏀劇┖闂達紝鐢ㄤ簬鐢ㄦ埛閫鍑哄拰鐢ㄦ埛鍒鋒柊鏃墮噴鏀劇┖闂?span lang="EN-US">,浣跨敤userInfoMutex榪涜綰跨▼闂存帶鍒?span lang="EN-US">*/ int destroyList(uList *list); (8)/*鍒涘緩鍛戒護瀛?span lang="EN-US">,com涓鴻榪斿洖鐨勫懡浠ゅ瓧,flag 涓烘秷鎭爣蹇?span lang="EN-US">,addtion 涓洪檮鍔犳爣蹇?span lang="EN-US">*/ void createCmd(command & com,int flag,char
addtion[]) (9)/*鍙戦佹秷鎭紝com涓鴻鍙戦佺殑娑堟伅錛?span lang="EN-US">servaddr涓鴻鍙戦佺殑鍦板潃錛?span lang="EN-US">attach涓烘枃浠墮檮浠朵俊鎭?span lang="EN-US">*/ void sendCmd(command com, struct sockaddr_in
servaddr,char attach[]); (10) /*鎶婃敹鍒扮殑娑堟伅鍔犲叆鍒版秷鎭槦鍒椾腑*/ void addMes(mesList *mHead,command cmd); (11) /*鎶婃秷鎭槦鍒椾腑澶撮儴鐨勮妭鐐規秷鎭彁鍙栧嚭鏉ョ敤浜庡鐞?span lang="EN-US">*/ int delMes(mesList *mHead,command *cmd); (12)/*鍒濆鍖栨搷浣滐紝椋為附鐧誨綍鏃跺垵濮嬪寲娑堟伅閾捐〃錛岀敤鎴烽摼琛紝淇″彿閲忥紝濂楁帴瀛椾俊鎭?span lang="EN-US">*/ void init(); (13)/*鐧誨綍鎿嶄綔,鍙戦佺敤鎴蜂笂綰挎秷鎭?span lang="EN-US">*/ void login(); (14)/*瑙f瀽鏀跺埌鐨勬秷鎭懡浠わ紝鎻愬彇鍚勪釜瀛楁*/ int
analysisCmd(command *cmd,char *buf); (15) /*鎺ユ敹娑堟伅綰跨▼澶勭悊鍑芥暟,灝嗘敹鍒扮殑娑堟伅鍔犲叆娑堟伅闃熷垪涓紝閫氳繃淇″彿閲?span lang="EN-US">waitNoFull鍜?span lang="EN-US">waitNoEmpty鍜屾秷鎭鐞嗙嚎紼嬭繘琛岄氫俊銆傛秷鎭槦鍒楃敤mesMutex涓庡叾浠栫嚎紼嬭繘琛岄氫俊錛屼繚璇佹秷鎭槦鍒楃殑姝g‘鎬?span lang="EN-US">*/ void
*receive(void *arg); (16)/*gtk鐣岄潰涓樉紺哄湪綰跨敤鎴蜂俊鎭?span lang="EN-US">*/ void showUser(uList *list); (17)/*鍦?span lang="EN-US">gtk鐣岄潰涓樉紺烘秷鎭?span lang="EN-US">*/ void showMessage(char *message); (18)/*鏄劇ず鏀跺埌鐨勪俊鎭?span lang="EN-US">*/ void showRecvMessage(char *host,char *message); (19)/*鍒嗘瀽鏂囦歡鐨勪俊鎭紝鎻愬彇鏈夌敤鐨勫瓧孌?span lang="EN-US">*/ void fileAnalysis(char *recv,int *fNum,char *fName,int
*fSize,int *fTime,int *fType); (20) /*淇濆瓨鏀跺埌鐨勫崟涓枃浠?span lang="EN-US">,saveName涓轟繚瀛樼殑鏂囦歡鍚?span lang="EN-US">*/ void saveSignalFile(char *saveName); (21)/*鍒嗘瀽鐩綍闄勪歡錛岃幏寰楃洰褰曟枃浠剁殑鏂囦歡鍚嶏紝鏂囦歡澶у皬錛屾枃浠剁被鍨?span lang="EN-US">*/ void getDirInfo(char *recv,char *fName,int *fSize,int
*fType); (22) /*淇濆瓨鐩綍,saveName涓鴻淇濆瓨鐨勭洰褰?span lang="EN-US">*/ void saveDir(char *saveName); (23)/*淇濆瓨鏂囦歡,recvType=1涓轟繚瀛樻枃浠訛紝recvType=2涓轟繚瀛樼殑鐩綍,浣跨敤fileMutex鏉ヨ緗簰鏂ユ?span lang="EN-US">*/ void saveFile(); (24)/*鏀跺埌鍗曚釜鏂囦歡*/ void receiveSignalFile(char *recvFileName); (25)/*鏀跺埌鍗曚釜鐩綍*/ void receiveDir(char *recvDirName); (26)/*鎺ユ敹鏂囦歡*/ void receiveFile(command cmd); (27)/*淇″彿澶勭悊綰跨▼,浠庢秷鎭槦鍒椾腑鍙栧嚭娑堟伅榪涜澶勭悊*/ void *process(void *arg); (28)/*鍙戦佹秷鎭?span lang="EN-US">*/ int sendMes(); (29) /*灝嗘枃浠跺悕榪涜杞崲*/ char *transName(char *fileName); (30)/*鍙戦佹枃浠?span lang="EN-US">*/ void sendFile(); (31)/*鍙戦佹枃浠跺す*/ void sendDir(); (32)/*鐢ㄦ埛鐐瑰嚮鍒鋒柊,鍒鋒柊鍦ㄧ嚎鐢ㄦ埛*/ void refresh(); (33) /*鐢ㄦ埛閫鍑?span lang="EN-US">*/ void quit(); (34)/*浼犺緭鏂囦歡澶規暟鎹紝閫掑綊鍑芥暟*/ void transferDir(int fd,char *dir); (35)/*鐩戝惉TCP濂楁帴鍙o紝鍙戦佹枃浠朵笌鏂囦歡澶圭嚎紼?span lang="EN-US">*/ void *sendData(void *arg); (36)/*鍒涘緩鑿滃崟*/ static void create_popup_menu(GtkWidget
*menu,GtkWidget *view); (37)/*鍙沖嚮閫変腑treeview,鏄劇ず浼犻佹枃浠朵笌鏂囦歡澶硅彍鍗?span lang="EN-US">*/ static gboolean showTreeView(GtkWidget
*eventBox,GdkEventButton *event,GtkWidget *menu); (38)/*閫夋嫨瑕佸彂閫佺殑鏂囦歡 */ static void selectFile(); (39)/*閫夋嫨瑕佸彂閫佺殑鏂囦歡澶?span lang="EN-US">*/ static void selectDir(); (40)/*閫夋嫨瑕佷繚瀛樼殑鏂囦歡鍚嶆垨鏂囦歡澶瑰悕*/ static void selectSaveFile(); 3.鎬葷粨 瀹炵幇浜?span lang="EN-US">linux涓嬮楦戒紶涔︾殑鍩烘湰鍔熻兘錛屽茍涓旇兘涓?span lang="EN-US">window涓嬮楦借繘琛岄氫俊錛屼紶鏂囦歡銆傜啛鎮変簡linux涓嬬綉緇滅紪紼嬶紝澶氱嚎紼嬬紪紼嬪強綰跨▼闂撮氫俊錛堜富瑕佺敤鍒頒俊鍙烽噺涓庝簰鏂ラ攣錛夈備絾鍔犲瘑瑙e瘑閭e潡娌℃湁瀹屾垚錛岀▼搴忕粨鏋勪笉鏄緢濂斤紝鐣岄潰鍋氬緱澶樊銆傛湁絀哄簲璇ョ湅鐪嬭璁℃ā寮?span lang="EN-US">. 鐣岄潰鎴浘錛堢晫闈㈡瘮杈冨瀮鍦?錛?/p>
闄勶細 椋為附鍗忚錛?http://bbs.chinaunix.net/viewthread.php?tid=1015775
鍦╨inux鐨勭綉緇滅紪紼嬩腑錛屽緢闀跨殑鏃墮棿閮藉湪浣跨敤select鏉ュ仛浜嬩歡瑙﹀彂銆傚湪linux鏂扮殑鍐呮牳涓紝鏈変簡涓縐嶆浛鎹㈠畠鐨勬満鍒訛紝灝辨槸epoll銆?br>
鐩告瘮浜巗elect錛宔poll鏈澶х殑濂藉鍦ㄤ簬瀹冧笉浼氶殢鐫鐩戝惉fd鏁扮洰鐨勫闀胯岄檷浣庢晥鐜囥傚洜涓哄湪鍐呮牳涓殑select瀹炵幇涓紝瀹冩槸閲囩敤杞鏉ュ鐞嗙殑錛岃疆璇㈢殑fd鏁扮洰瓚婂錛岃嚜鐒惰楁椂瓚婂銆傚茍涓旓紝鍦╨inux/posix_types.h澶存枃浠舵湁榪欐牱鐨勫0鏄庯細
epoll鏈変袱縐嶆ā寮?Edge Triggered(綆縐癊T) 鍜?Level
Triggered(綆縐癓T).鍦ㄩ噰鐢ㄨ繖涓ょ妯″紡鏃惰娉ㄦ剰鐨勬槸,濡傛灉閲囩敤ET妯″紡,閭d箞浠呭綋鐘舵佸彂鐢熷彉鍖栨椂鎵嶄細閫氱煡,鑰岄噰鐢↙T妯″紡綾諱技浜庡師鏉ョ殑
select/poll鎿嶄綔,鍙榪樻湁娌℃湁澶勭悊鐨勪簨浠跺氨浼氫竴鐩撮氱煡.
榪愯server鍜宑lient鍙戠幇,server浠呬粎璇誨彇浜?瀛楄妭鐨勬暟鎹?鑰宑lient鍏跺疄鍙戦佷簡10瀛楄妭鐨勬暟鎹?涔熷氨鏄,server浠呭綋絎竴嬈?
鐩戝惉鍒頒簡EPOLLIN浜嬩歡,鐢變簬娌℃湁璇誨彇瀹屾暟鎹?鑰屼笖閲囩敤鐨勬槸ET妯″紡,鐘舵佸湪姝や箣鍚庝笉鍙戠敓鍙樺寲,鍥犳server鍐嶄篃鎺ユ敹涓嶅埌EPOLLIN浜嬩歡浜?
RPC鏄痝libc鎻愪緵鐨勫嚱鏁板弬鏁?榪斿洖鍊煎皝瑁呮湇鍔? 騫跺皢灝佽緇撴灉閫氳繃緗戠粶浼犲埌鏈嶅姟鍣?
RPC鏈嶅姟绔鍏堣鍚姩portmapper鏈嶅姟.
嫻嬭瘯涓涓畝鍗曠殑RPC浼犺緭紺轟緥, 鍏堝畾涔変竴涓ā鏉挎枃浠秚est.x
version VERSION{
int int_echo(int)=1;
int get_str_len(string)=2;
int add ( int, int ) = 3;
}=1;
}=30000;
鐒跺悗鍙互鐢╮pcgen鐢熸垚涓涓狹akefile:
榪欎細鐢熸垚Makefile, 瀹㈡埛绔拰鏈嶅姟绔殑紼嬪簭, 鍜屽嚱鏁扮ず渚?
鎴戜滑鎵嬪伐淇敼涓涓婱akefile
# Parameters
CLIENT = test_client
SERVER = test_server
SOURCES_CLNT.c =
SOURCES_CLNT.h =
SOURCES_SVC.c =
SOURCES_SVC.h =
SOURCES.x = test.x
TARGETS_SVC.c = test_svc.c test_server.c test_xdr.c
TARGETS_CLNT.c = test_clnt.c test_client.c test_xdr.c
TARGETS = test.h test_xdr.c test_clnt.c test_svc.c
OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
# Compiler flags
CFLAGS += -g -pipe
LDLIBS += -lnsl
RPCGENFLAGS = -N
# Targets
all : $(CLIENT) $(SERVER)
$(TARGETS) : $(SOURCES.x)
rpcgen $(RPCGENFLAGS) $(SOURCES.x)
$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)
$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c)
$(CLIENT) : $(OBJECTS_CLNT)
$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)
$(SERVER) : $(OBJECTS_SVC)
$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)
clean:
$(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)
淇敼test_server.c鏈嶅姟绔殑澶勭悊鍑芥暟, 鎻愪緵3縐嶆湇鍔?
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/
#include "test.h"
int *
int_echo_1_svc(int arg1, struct svc_req *rqstp)
{
static int result;
//echo.
result=arg1;
printf("[RPC1] source=%d, echo=%d\n", arg1, result);
return &result;
}
int *
get_str_len_1_svc(char *arg1, struct svc_req *rqstp)
{
static int result;
//get strlen.
result=strlen(arg1);
printf("[PRC2] str=%s, len=%d\n", arg1, result);
return &result;
}
int *
add_1_svc(int arg1, int arg2, struct svc_req *rqstp)
{
static int result;
result=arg1+arg2;
printf("[RPC3] %d+%d=%d\n", arg1, arg2, result);
return &result;
}
瀹㈡埛绔痶est_client.c, 璋冪敤榪欎笁縐嶆湇鍔?
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/
#include "test.h"
void
testprog_1(char *host)
{
CLIENT *clnt;
int *result_1;
int int_echo_1_arg1=55;
int *result_2;
char *get_str_len_1_arg1="Hello, world";
int *result_3;
int add_1_arg1=10;
int add_1_arg2=20;
clnt = clnt_create (host, TESTPROG, VERSION, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}
result_1 = int_echo_1(int_echo_1_arg1, clnt);
if (result_1 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
printf("[PRC1] echo %d, source %d\n", *result_1,
int_echo_1_arg1);
result_2 = get_str_len_1(get_str_len_1_arg1, clnt);
if (result_2 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
printf("[RPC2] return %d, should %d\n", *result_2,
strlen(get_str_len_1_arg1));
result_3 = add_1(add_1_arg1, add_1_arg2, clnt);
if (result_3 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
printf("[PRC3] %d+%d=%d\n", add_1_arg1, add_1_arg2,
*result_3);
clnt_destroy (clnt);
}
鐢熸垚鍙墽琛岀▼搴弔est_server鍜宼est_client.
鎴戜滑鍚姩./test_server, 鐢╮pcinfo鐪嬬湅:
program vers proto port
100000 2 tcp 111 portmapper
30000 1 udp 36307
30000 1 tcp 34883
Bingo! 鍚姩鎴愬姛.
鍐嶅紑涓粓绔? 灝濊瘯涓涓嬭皟鐢?
./test_client 127.0.0.1
[PRC1] echo 55, source 55
[RPC2] return 12, should 12
[PRC3] 10+20=30
姝f槸鎴戜滑鏈熸湜鐨?
Add By錛欽ackxiang
]]>
錛?錛夎凱浠f湇鍔″櫒錛堟棤榪涚▼鎺у埗)
錛?錛夊茍鍙戞湇鍔″櫒錛屾瘡涓鎴瘋姹俧ork 涓涓瓙榪涚▼
錛?錛夐鍏堟淳鐢熷瓙榪涚▼錛屾瘡涓瓙榪涚▼鏃犱繚鎶ゅ湴璋冪敤accept
錛?錛夐鍏堟淳鐢熷瓙榪涚▼錛屼嬌鐢ㄦ枃浠朵笂閿佷繚鎶ccept
錛?錛夐鍏堟淳鐢熷瓙榪涚▼錛屼嬌鐢ㄧ嚎紼嬩簰鏂ラ攣淇濇姢accept錛堝叡浜唴瀛?
錛?錛夐鍏堟淳鐢熷瓙榪涚▼錛岀埗榪涚▼鍚戝瓙榪涚▼浼犻掑鎺ュ彛鎻忚堪瀛?br>錛?錛夊茍鍙戞湇鍔″櫒錛屾瘡涓鎴瘋姹傚垱寤轟竴涓嚎紼?br>錛?錛夐鍏堝垱寤虹嚎紼嬫湇鍔″櫒錛屼嬌鐢ㄤ簰鏂ラ攣涓婇攣淇濇姢accept
錛?錛夐鍏堝垱寤虹嚎紼嬫湇鍔″櫒錛岀敱涓葷嚎紼嬭皟鐢╝ccept.
嫻嬭瘯鐢ㄤ緥 瀹㈡埛鍒涘緩5涓繘紼嬶紝姣忎釜鍙戣搗500涓繛鎺ワ紝姣忎釜榪炴帴鍐欏洓涓瓧鑺傛暟鎹?br> 鎬葷殑鐢ㄦ埛鏃墮棿錛堢錛? 鎬葷殑緋葷粺鏃墮棿錛堢錛?br>錛?錛? 0.012 0.16001
錛?錛? 0.008 0.256016
錛?錛? 0.016 0.268016
錛?錛? 0.020001 0.380023
錛?錛? 0.012 0.308019
錛?錛? 0.068003 0.464029
錛?錛? 0.024001 0.224014
錛?錛? 0.012 0.280017
錛?錛? 0.0160001 0.268016
]]>
]]>
#define __FD_SETSIZE 1024
琛ㄧずselect鏈澶氬悓鏃剁洃鍚?024涓猣d錛屽綋鐒訛紝鍙互閫氳繃淇敼澶存枃浠跺啀閲嶇紪璇戝唴鏍告潵鎵╁ぇ榪欎釜鏁扮洰錛屼絾榪欎技涔庡茍涓嶆不鏈?br>
epoll鐨勬帴鍙i潪甯哥畝鍗曪紝涓鍏卞氨涓変釜鍑芥暟錛?br>
1. int epoll_create(int size);
鍒?
寤轟竴涓猠poll鐨勫彞鏌勶紝size鐢ㄦ潵鍛婅瘔鍐呮牳榪欎釜鐩戝惉鐨勬暟鐩竴鍏辨湁澶氬ぇ銆傝繖涓弬鏁頒笉鍚屼簬select()涓殑絎竴涓弬鏁幫紝緇欏嚭鏈澶х洃鍚殑fd+1鐨勫箋?
闇瑕佹敞鎰忕殑鏄紝褰撳垱寤哄ソepoll鍙ユ焺鍚庯紝瀹冨氨鏄細鍗犵敤涓涓猣d鍊鹼紝鍦╨inux涓嬪鏋滄煡鐪?proc/榪涚▼id/fd/錛屾槸鑳藉鐪嬪埌榪欎釜fd鐨勶紝鎵浠ュ湪
浣跨敤瀹宔poll鍚庯紝蹇呴』璋冪敤close()鍏抽棴錛屽惁鍒欏彲鑳藉鑷磃d琚楀敖銆?br>
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll鐨勪簨浠舵敞鍐屽嚱鏁幫紝瀹冧笉鍚屼笌select()鏄湪鐩戝惉浜嬩歡鏃跺憡璇夊唴鏍歌鐩戝惉浠涔堢被鍨嬬殑浜嬩歡錛岃屾槸鍦ㄨ繖閲屽厛娉ㄥ唽瑕佺洃鍚殑浜嬩歡綾誨瀷銆傜涓涓弬鏁版槸epoll_create()鐨勮繑鍥炲鹼紝絎簩涓弬鏁拌〃紺哄姩浣滐紝鐢ㄤ笁涓畯鏉ヨ〃紺猴細
EPOLL_CTL_ADD錛氭敞鍐屾柊鐨刦d鍒癳pfd涓紱
EPOLL_CTL_MOD錛氫慨鏀瑰凡緇忔敞鍐岀殑fd鐨勭洃鍚簨浠訛紱
EPOLL_CTL_DEL錛氫粠epfd涓垹闄や竴涓猣d錛?br>
絎笁涓弬鏁版槸闇瑕佺洃鍚殑fd錛岀鍥涗釜鍙傛暟鏄憡璇夊唴鏍擱渶瑕佺洃鍚粈涔堜簨錛宻truct epoll_event緇撴瀯濡備笅錛?br>
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
events鍙互鏄互涓嬪嚑涓畯鐨勯泦鍚堬細
EPOLLIN 錛氳〃紺哄搴旂殑鏂囦歡鎻忚堪絎﹀彲浠ヨ錛堝寘鎷绔疭OCKET姝e父鍏抽棴錛夛紱
EPOLLOUT錛氳〃紺哄搴旂殑鏂囦歡鎻忚堪絎﹀彲浠ュ啓錛?br>
EPOLLPRI錛氳〃紺哄搴旂殑鏂囦歡鎻忚堪絎︽湁绱фョ殑鏁版嵁鍙錛堣繖閲屽簲璇ヨ〃紺烘湁甯﹀鏁版嵁鍒版潵錛夛紱
EPOLLERR錛氳〃紺哄搴旂殑鏂囦歡鎻忚堪絎﹀彂鐢熼敊璇紱
EPOLLHUP錛氳〃紺哄搴旂殑鏂囦歡鎻忚堪絎﹁鎸傛柇錛?br>
EPOLLET錛?灝咵POLL璁句負杈圭紭瑙﹀彂(Edge Triggered)妯″紡錛岃繖鏄浉瀵逛簬姘村鉤瑙﹀彂(Level Triggered)鏉ヨ鐨勩?br>
EPOLLONESHOT錛氬彧鐩戝惉涓嬈′簨浠訛紝褰撶洃鍚畬榪欐浜嬩歡涔嬪悗錛屽鏋滆繕闇瑕佺戶緇洃鍚繖涓猻ocket鐨勮瘽錛岄渶瑕佸啀嬈℃妸榪欎釜socket鍔犲叆鍒癊POLL闃熷垪閲?br>
3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
絳?
寰呬簨浠剁殑浜х敓錛岀被浼間簬select()璋冪敤銆傚弬鏁癳vents鐢ㄦ潵浠庡唴鏍稿緱鍒頒簨浠剁殑闆嗗悎錛宮axevents鍛婁箣鍐呮牳榪欎釜events鏈夊澶э紝榪欎釜
maxevents鐨勫間笉鑳藉ぇ浜庡垱寤篹poll_create()鏃剁殑size錛屽弬鏁皌imeout鏄秴鏃舵椂闂達紙姣錛?浼氱珛鍗寵繑鍥烇紝-1灝嗕笉紜畾錛屼篃鏈?
璇存硶璇存槸姘鎬箙闃誨錛夈傝鍑芥暟榪斿洖闇瑕佸鐞嗙殑浜嬩歡鏁扮洰錛屽榪斿洖0琛ㄧず宸茶秴鏃躲?br>
--------------------------------------------------------------------------------------------
浠巑an鎵嬪唽涓紝寰楀埌ET鍜孡T鐨勫叿浣撴弿榪板涓?br>
EPOLL浜嬩歡鏈変袱縐嶆ā鍨嬶細
Edge Triggered (ET)
Level Triggered (LT)
鍋囧鏈夎繖鏍蜂竴涓緥瀛愶細
1. 鎴戜滑宸茬粡鎶婁竴涓敤鏉ヤ粠綆¢亾涓鍙栨暟鎹殑鏂囦歡鍙ユ焺(RFD)娣誨姞鍒癳poll鎻忚堪絎?br>
2. 榪欎釜鏃跺欎粠綆¢亾鐨勫彟涓绔鍐欏叆浜?KB鐨勬暟鎹?br>
3. 璋冪敤epoll_wait(2)錛屽茍涓斿畠浼氳繑鍥濺FD錛岃鏄庡畠宸茬粡鍑嗗濂借鍙栨搷浣?br>
4. 鐒跺悗鎴戜滑璇誨彇浜?KB鐨勬暟鎹?br>
5. 璋冪敤epoll_wait(2)......
Edge Triggered 宸ヤ綔妯″紡錛?br>
濡?
鏋滄垜浠湪絎?姝ュ皢RFD娣誨姞鍒癳poll鎻忚堪絎︾殑鏃跺欎嬌鐢ㄤ簡EPOLLET鏍囧織錛岄偅涔堝湪絎?姝ヨ皟鐢╡poll_wait(2)涔嬪悗灝嗘湁鍙兘浼氭寕璧鳳紝鍥犱負鍓?
浣欑殑鏁版嵁榪樺瓨鍦ㄤ簬鏂囦歡鐨勮緭鍏ョ紦鍐插尯鍐咃紝鑰屼笖鏁版嵁鍙戝嚭绔繕鍦ㄧ瓑寰呬竴涓拡瀵瑰凡緇忓彂鍑烘暟鎹殑鍙嶉淇℃伅銆傚彧鏈夊湪鐩戣鐨勬枃浠跺彞鏌勪笂鍙戠敓浜嗘煇涓簨浠剁殑鏃跺?ET
宸ヤ綔妯″紡鎵嶄細姹囨姤浜嬩歡銆傚洜姝ゅ湪絎?姝ョ殑鏃跺欙紝璋冪敤鑰呭彲鑳戒細鏀懼純絳夊緟浠嶅湪瀛樺湪浜庢枃浠惰緭鍏ョ紦鍐插尯鍐呯殑鍓╀綑鏁版嵁銆傚湪涓婇潰鐨勪緥瀛愪腑錛屼細鏈変竴涓簨浠朵駭鐢熷湪RFD鍙ユ焺
涓婏紝鍥犱負鍦ㄧ2姝ユ墽琛屼簡涓涓啓鎿嶄綔錛岀劧鍚庯紝浜嬩歡灝嗕細鍦ㄧ3姝ヨ閿姣併傚洜涓虹4姝ョ殑璇誨彇鎿嶄綔娌℃湁璇葷┖鏂囦歡杈撳叆緙撳啿鍖哄唴鐨勬暟鎹紝鍥犳鎴戜滑鍦ㄧ5姝ヨ皟鐢?
epoll_wait(2)瀹屾垚鍚庯紝鏄惁鎸傝搗鏄笉紜畾鐨勩俥poll宸ヤ綔鍦‥T妯″紡鐨勬椂鍊欙紝蹇呴』浣跨敤闈為樆濉炲鎺ュ彛錛屼互閬垮厤鐢變簬涓涓枃浠跺彞鏌勭殑闃誨璇?闃誨
鍐欐搷浣滄妸澶勭悊澶氫釜鏂囦歡鎻忚堪絎︾殑浠誨姟楗挎銆傛渶濂戒互涓嬮潰鐨勬柟寮忚皟鐢‥T妯″紡鐨別poll鎺ュ彛錛屽湪鍚庨潰浼氫粙緇嶉伩鍏嶅彲鑳界殑緙洪櫡銆?br>
i 鍩轟簬闈為樆濉炴枃浠跺彞鏌?br>
ii 鍙湁褰搑ead(2)鎴栬厀rite(2)榪斿洖EAGAIN鏃舵墠闇瑕佹寕璧鳳紝絳夊緟銆?span style="font-weight: bold; color: #0001ff;">浣嗚繖騫朵笉鏄姣忔read()鏃墮兘闇瑕佸驚鐜錛岀洿鍒拌鍒頒駭鐢熶竴涓狤AGAIN鎵嶈涓烘嬈′簨浠跺鐞嗗畬鎴愶紝褰搑ead()榪斿洖鐨勮鍒扮殑鏁版嵁闀垮害灝忎簬璇鋒眰鐨勬暟鎹暱搴︽椂錛屽氨鍙互紜畾姝ゆ椂緙撳啿涓凡娌℃湁鏁版嵁浜嗭紝涔熷氨鍙互璁や負姝や簨璇諱簨浠跺凡澶勭悊瀹屾垚銆?/span>
Level Triggered 宸ヤ綔妯″紡
鐩?
鍙嶇殑錛屼互LT鏂瑰紡璋冪敤epoll鎺ュ彛鐨勬椂鍊欙紝瀹冨氨鐩稿綋浜庝竴涓熷害姣旇緝蹇殑poll(2)錛屽茍涓旀棤璁哄悗闈㈢殑鏁版嵁鏄惁琚嬌鐢紝鍥犳浠栦滑鍏鋒湁鍚屾牱鐨勮亴鑳姐傚洜涓哄嵆
浣夸嬌鐢‥T妯″紡鐨別poll錛屽湪鏀跺埌澶氫釜chunk鐨勬暟鎹殑鏃跺欎粛鐒朵細浜х敓澶氫釜浜嬩歡銆傝皟鐢ㄨ呭彲浠ヨ瀹欵POLLONESHOT鏍囧織錛屽湪
epoll_wait(2)鏀跺埌浜嬩歡鍚巈poll浼氫笌浜嬩歡鍏寵仈鐨勬枃浠跺彞鏌勪粠epoll鎻忚堪絎︿腑紱佹鎺夈傚洜姝ゅ綋EPOLLONESHOT璁懼畾鍚庯紝浣跨敤甯︽湁
EPOLL_CTL_MOD鏍囧織鐨別poll_ctl(2)澶勭悊鏂囦歡鍙ユ焺灝辨垚涓鴻皟鐢ㄨ呭繀欏諱綔鐨勪簨鎯呫?br>
鐒跺悗璇︾粏瑙i噴ET, LT:
LT(level
triggered)鏄己鐪佺殑宸ヤ綔鏂瑰紡錛屽茍涓斿悓鏃舵敮鎸乥lock鍜宯o-block
socket.鍦ㄨ繖縐嶅仛娉曚腑錛屽唴鏍稿憡璇変綘涓涓枃浠舵弿榪扮鏄惁灝辯華浜嗭紝鐒跺悗浣犲彲浠ュ榪欎釜灝辯華鐨刦d榪涜IO鎿嶄綔銆傚鏋滀綘涓嶄綔浠諱綍鎿嶄綔錛屽唴鏍歌繕鏄細緇х畫閫氱煡浣?
鐨勶紝鎵浠ワ紝榪欑妯″紡緙栫▼鍑洪敊璇彲鑳芥ц灝忎竴鐐廣備紶緇熺殑select/poll閮芥槸榪欑妯″瀷鐨勪唬琛紟
ET(edge-triggered)
鏄珮閫熷伐浣滄柟寮忥紝鍙敮鎸乶o-block
socket銆傚湪榪欑妯″紡涓嬶紝褰撴弿榪扮浠庢湭灝辯華鍙樹負灝辯華鏃訛紝鍐呮牳閫氳繃epoll鍛婅瘔浣犮傜劧鍚庡畠浼氬亣璁句綘鐭ラ亾鏂囦歡鎻忚堪絎﹀凡緇忓氨緇紝騫朵笖涓嶄細鍐嶄負閭d釜鏂囦歡鎻忚堪
絎﹀彂閫佹洿澶氱殑灝辯華閫氱煡錛岀洿鍒頒綘鍋氫簡鏌愪簺鎿嶄綔瀵艱嚧閭d釜鏂囦歡鎻忚堪絎︿笉鍐嶄負灝辯華鐘舵佷簡(姣斿錛屼綘鍦ㄥ彂閫侊紝鎺ユ敹鎴栬呮帴鏀惰姹傦紝鎴栬呭彂閫佹帴鏀剁殑鏁版嵁灝戜簬涓瀹氶噺鏃跺鑷?
浜嗕竴涓狤WOULDBLOCK 閿欒錛夈備絾鏄娉ㄦ剰錛屽鏋滀竴鐩翠笉瀵硅繖涓猣d浣淚O鎿嶄綔(浠庤屽鑷村畠鍐嶆鍙樻垚鏈氨緇?錛屽唴鏍鎬笉浼氬彂閫佹洿澶氱殑閫氱煡(only
once),涓嶈繃鍦═CP鍗忚涓紝ET妯″紡鐨勫姞閫熸晥鐢ㄤ粛闇瑕佹洿澶氱殑benchmark紜錛堣繖鍙ヨ瘽涓嶇悊瑙o級銆?/span>
鍦?
璁稿嫻嬭瘯涓垜浠細鐪嬪埌濡傛灉娌℃湁澶ч噺鐨刬dle
-connection鎴栬卍ead-connection錛宔poll鐨勬晥鐜囧茍涓嶄細姣攕elect/poll楂樺緢澶氾紝浣嗘槸褰撴垜浠亣鍒板ぇ閲忕殑idle-
connection(渚嬪WAN鐜涓瓨鍦ㄥぇ閲忕殑鎱㈤熻繛鎺?錛屽氨浼氬彂鐜癳poll鐨勬晥鐜囧ぇ澶ч珮浜巗elect/poll銆傦紙鏈祴璇曪級
鍙﹀錛屽綋浣跨敤epoll鐨凟T妯″瀷鏉ュ伐浣滄椂錛屽綋浜х敓浜嗕竴涓狤POLLIN浜嬩歡鍚庯紝
璇繪暟鎹殑鏃跺欓渶瑕佽冭檻鐨勬槸褰搑ecv()榪斿洖鐨勫ぇ灝忓鏋滅瓑浜庤姹傜殑澶у皬錛岄偅涔堝緢鏈夊彲鑳芥槸緙撳啿鍖鴻繕鏈夋暟鎹湭璇誨畬錛屼篃鎰忓懗鐫璇ユ浜嬩歡榪樻病鏈夊鐞嗗畬錛屾墍浠ヨ繕闇瑕佸啀嬈¤鍙?/span>
錛?br>
while(rs)
{
buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);
if(buflen < 0)
{
// 鐢變簬鏄潪闃誨鐨勬ā寮?鎵浠ュ綋errno涓篍AGAIN鏃?琛ㄧず褰撳墠緙撳啿鍖哄凡鏃犳暟鎹彲璇?br>
// 鍦ㄨ繖閲屽氨褰撲綔鏄嬈′簨浠跺凡澶勭悊澶?
if(errno == EAGAIN)
break;
else
return;
}
else if(buflen == 0)
{
// 榪欓噷琛ㄧず瀵圭鐨剆ocket宸叉甯稿叧闂?
}
if(buflen == sizeof(buf)
rs = 1; // 闇瑕佸啀嬈¤鍙?/span>
else
rs = 0;
}
榪?
鏈夛紝鍋囧鍙戦佺嫻侀噺澶т簬鎺ユ敹绔殑嫻侀噺(鎰忔濇槸epoll鎵鍦ㄧ殑紼嬪簭璇繪瘮杞彂鐨剆ocket瑕佸揩),鐢變簬鏄潪闃誨鐨剆ocket,閭d箞send()鍑芥暟铏界劧
榪斿洖,浣嗗疄闄呯紦鍐插尯鐨勬暟鎹茍鏈湡姝e彂緇欐帴鏀剁,榪欐牱涓嶆柇鐨勮鍜屽彂錛屽綋緙撳啿鍖烘弧鍚庝細浜х敓EAGAIN閿欒(鍙傝僲an
send),鍚屾椂,涓嶇悊浼氳繖嬈¤姹傚彂閫佺殑鏁版嵁.鎵浠?闇瑕佸皝瑁卻ocket_send()鐨勫嚱鏁扮敤鏉ュ鐞嗚繖縐嶆儏鍐?璇ュ嚱鏁頒細灝介噺灝嗘暟鎹啓瀹屽啀榪斿洖錛岃繑鍥?
-1琛ㄧず鍑洪敊銆傚湪socket_send()鍐呴儴,褰撳啓緙撳啿宸叉弧(send()榪斿洖-1,涓攅rrno涓篍AGAIN),閭d箞浼氱瓑寰呭悗鍐嶉噸璇?榪欑鏂瑰紡騫?
涓嶅緢瀹岀編,鍦ㄧ悊璁轟笂鍙兘浼氶暱鏃墮棿鐨勯樆濉炲湪socket_send()鍐呴儴,浣嗘殏娌℃湁鏇村ソ鐨勫姙娉?
ssize_t socket_send(int sockfd, const char* buffer, size_t buflen)
{
ssize_t tmp;
size_t total = buflen;
const char *p = buffer;
while(1)
{
tmp = send(sockfd, p, total, 0);
if(tmp < 0)
{
// 褰搒end鏀跺埌淇″彿鏃?鍙互緇х畫鍐?浣嗚繖閲岃繑鍥?1.
if(errno == EINTR)
return -1;
// 褰搒ocket鏄潪闃誨鏃?濡傝繑鍥炴閿欒,琛ㄧず鍐欑紦鍐查槦鍒楀凡婊?
// 鍦ㄨ繖閲屽仛寤舵椂鍚庡啀閲嶈瘯.
if(errno == EAGAIN)
{
usleep(1000);
continue;
}
return -1;
}
if((size_t)tmp == total)
return buflen;
total -= tmp;
p += tmp;
}
return tmp;
}
]]>
epoll瀛︿範絎旇
浠ヤ唬鐮佹潵璇存槑闂:
棣栧厛緇欏嚭server鐨勪唬鐮?闇瑕佽鏄庣殑鏄瘡嬈ccept鐨勮繛鎺?鍔犲叆鍙闆嗙殑鏃跺欓噰鐢ㄧ殑閮芥槸ET妯″紡,鑰屼笖鎺ユ敹緙撳啿鍖烘槸5瀛楄妭鐨?涔熷氨鏄瘡嬈″彧鎺ユ敹5瀛楄妭鐨勬暟鎹?
#include
<
sys
/
socket.h
>
#include
<
sys
/
epoll.h
>
#include
<
netinet
/
in.h
>
#include
<
arpa
/
inet.h
>
#include
<
fcntl.h
>
#include
<
unistd.h
>
#include
<
stdio.h
>
#include
<
errno.h
>
using namespace std;
#define MAXLINE
5
#define OPEN_MAX
100
#define LISTENQ
20
#define SERV_PORT
5000
#define INFTIM
1000
void setnonblocking(
int
sock)
{
int
opts;
opts
=
fcntl(sock,F_GETFL);
if
(opts
<
0
)
{
perror(
"
fcntl(sock,GETFL)
"
);
exit
(
1
);
}
opts
=
opts|O_NONBLOCK;
if
(fcntl(sock,F_SETFL,opts)
<
0
)
{
perror(
"
fcntl(sock,SETFL,opts)
"
);
exit
(
1
);
}
}
int
main()
{
int
i, maxi, listenfd, connfd, sockfd,epfd,nfds;
ssize_t n;
char line[MAXLINE];
socklen_t clilen;
//
澹版槑epoll_event緇撴瀯浣撶殑鍙橀噺,ev鐢ㄤ簬娉ㄥ唽浜嬩歡,鏁扮粍鐢ㄤ簬鍥炰紶瑕佸鐞嗙殑浜嬩歡
struct epoll_event ev,events[
20
];
//
鐢熸垚鐢ㄤ簬澶勭悊accept鐨別poll涓撶敤鐨勬枃浠舵弿榪扮
epfd
=
epoll_create(
256
);
struct sockaddr_in clientaddr;
struct sockaddr_in serveraddr;
listenfd
=
socket(AF_INET, SOCK_STREAM,
0
);
//
鎶妔ocket璁劇疆涓洪潪闃誨鏂瑰紡
//
setnonblocking(listenfd);
//
璁劇疆涓庤澶勭悊鐨勪簨浠剁浉鍏崇殑鏂囦歡鎻忚堪絎?br>
ev.data.fd
=
listenfd;
//
璁劇疆瑕佸鐞嗙殑浜嬩歡綾誨瀷
ev.events
=
EPOLLIN|EPOLLET;
//
ev.events
=
EPOLLIN;
//
娉ㄥ唽epoll浜嬩歡
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,
&
ev);
bzero(
&
serveraddr, sizeof(serveraddr));
serveraddr.sin_family
=
AF_INET;
char
*
local_addr
=
"
127.0.0.1
"
;
inet_aton(local_addr,
&
(serveraddr.sin_addr));
//
htons(SERV_PORT);
serveraddr.sin_port
=
htons(SERV_PORT);
bind(listenfd,(sockaddr
*
)
&
serveraddr, sizeof(serveraddr));
listen(listenfd, LISTENQ);
maxi
=
0
;
for
( ; ; ) {
//
絳夊緟epoll浜嬩歡鐨勫彂鐢?br>
nfds
=
epoll_wait(epfd,events,
20
,
500
);
//
澶勭悊鎵鍙戠敓鐨勬墍鏈変簨浠?nbsp;
for
(i
=
0
;i
<
nfds;
++
i)
{
if
(events[i].data.fd
==
listenfd)
{
connfd
=
accept(listenfd,(struct sockaddr
*
)
&
clientaddr,
&
clilen);
if
(connfd
<
0
){
perror(
"
connfd<0
"
);
exit
(
1
);
}
//
setnonblocking(connfd);
char
*
str
=
inet_ntoa(clientaddr.sin_addr);
cout
<<
"
accapt a connection from
"
<<
str
<<
endl;
//
璁劇疆鐢ㄤ簬璇繪搷浣滅殑鏂囦歡鎻忚堪絎?br>
ev.data.fd
=
connfd;
//
璁劇疆鐢ㄤ簬娉ㄦ祴鐨勮鎿嶄綔浜嬩歡
ev.events
=
EPOLLIN|EPOLLET;
//
ev.events
=
EPOLLIN;
//
娉ㄥ唽ev
epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,
&
ev);
}
else
if
(events[i].events
&
EPOLLIN)
{
cout
<<
"
EPOLLIN
"
<<
endl;
if
( (sockfd
=
events[i].data.fd)
<
0
)
continue;
if
( (n
=
read(sockfd, line, MAXLINE))
<
0
) {
if
(errno
==
ECONNRESET) {
close(sockfd);
events[i].data.fd
=
-
1
;
}
else
std::cout
<<
"
readline error
"
<<
std::endl;
}
else
if
(n
==
0
) {
close(sockfd);
events[i].data.fd
=
-
1
;
}
line[n]
=
'
\0';
cout
<<
"
read
"
<<
line
<<
endl;
//
璁劇疆鐢ㄤ簬鍐欐搷浣滅殑鏂囦歡鎻忚堪絎?br>
ev.data.fd
=
sockfd;
//
璁劇疆鐢ㄤ簬娉ㄦ祴鐨勫啓鎿嶄綔浜嬩歡
ev.events
=
EPOLLOUT|EPOLLET;
//
淇敼sockfd涓婅澶勭悊鐨勪簨浠朵負EPOLLOUT
//
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,
&
ev);
}
else
if
(events[i].events
&
EPOLLOUT)
{
sockfd
=
events[i].data.fd;
write(sockfd, line, n);
//
璁劇疆鐢ㄤ簬璇繪搷浣滅殑鏂囦歡鎻忚堪絎?br>
ev.data.fd
=
sockfd;
//
璁劇疆鐢ㄤ簬娉ㄦ祴鐨勮鎿嶄綔浜嬩歡
ev.events
=
EPOLLIN|EPOLLET;
//
淇敼sockfd涓婅澶勭悊鐨勪簨浠朵負EPOLIN
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,
&
ev);
}
}
}
return
0
;
}
涓嬮潰緇欏嚭嫻嬭瘯鎵鐢ㄧ殑Perl鍐欑殑client绔?鍦╟lient涓彂閫?0瀛楄妭鐨勬暟鎹?鍚屾椂璁ヽlient鍦ㄥ彂閫佸畬鏁版嵁涔嬪悗榪涘叆姝誨驚鐜? 涔熷氨鏄湪鍙戦佸畬涔嬪悗榪炴帴鐨勭姸鎬佷笉鍙戠敓鏀瑰彉--鏃笉鍐嶅彂閫佹暟鎹? 涔熶笉鍏抽棴榪炴帴,榪欐牱鎵嶈兘瑙傚療鍑簊erver鐨勭姸鎬?
use IO::Socket;
my $host
=
"
127.0.0.1
"
;
my $port
=
5000
;
my $socket
=
IO::Socket::INET
->
new
(
"
$host:$port
"
)
or
die
"
create socket error $@
"
;
my $msg_out
=
"
1234567890
"
;
print $socket $msg_out;
print
"
now send over, go to sleep
\n
"
;
while
(
1
)
{
sleep(
1
);
}
(鍙嬫儏鎻愮ず:涓婇潰鐨勮繖涓祴璇曞鎴風,褰撲綘鍏抽棴瀹冪殑鏃跺欎細鍐嶆鍑哄彂IO鍙浜嬩歡緇檚erver,姝ゆ椂server灝變細鍘昏鍙栧墿涓嬬殑5瀛楄妭鏁版嵁浜?浣嗘槸榪欎竴浜嬩歡涓庡墠闈㈡弿榪扮殑ET鎬ц川騫朵笉鐭涚浘.)
濡傛灉鎴戜滑鎶奵lient鏀逛負榪欐牱:
use IO::Socket;
my $host
=
"
127.0.0.1
"
;
my $port
=
5000
;
my $socket
=
IO::Socket::INET
->
new
(
"
$host:$port
"
)
or
die
"
create socket error $@
"
;
my $msg_out
=
"
1234567890
"
;
print $socket $msg_out;
print
"
now send over, go to sleep
\n
"
;
sleep(
5
);
print
"
5 second gone
send another line\n
"
;
print $socket $msg_out;
while
(
1
)
{
sleep(
1
);
}
鍙互鍙戠幇,鍦╯erver鎺ユ敹瀹?瀛楄妭鐨勬暟鎹箣鍚庝竴鐩寸洃鍚笉鍒癱lient鐨勪簨浠?鑰屽綋client浼戠湢5縐掍箣鍚庨噸鏂板彂閫佹暟鎹?server鍐嶆鐩戝惉鍒頒簡鍙樺寲,鍙笉榪囧洜涓哄彧鏄鍙栦簡5涓瓧鑺?浠嶇劧鏈?0涓瓧鑺傜殑鏁版嵁(client絎簩嬈″彂閫佺殑鏁版嵁)娌℃湁鎺ユ敹瀹?
濡傛灉涓婇潰鐨勫疄楠屼腑,瀵筧ccept鐨剆ocket閮介噰鐢ㄧ殑鏄疞T妯″紡,閭d箞鍙榪樻湁鏁版嵁鐣欏湪buffer涓?server灝變細緇х畫寰楀埌閫氱煡,璇昏呭彲浠ヨ嚜琛屾敼鍔ㄤ唬鐮佽繘琛屽疄楠?
鍩?
浜庤繖涓や釜瀹為獙,鍙互寰楀嚭榪欐牱鐨勭粨璁?ET妯″紡浠呭綋鐘舵佸彂鐢熷彉鍖栫殑鏃跺欐墠鑾峰緱閫氱煡,榪欓噷鎵璋撶殑鐘舵佺殑鍙樺寲騫朵笉鍖呮嫭緙撳啿鍖轟腑榪樻湁鏈鐞嗙殑鏁版嵁,涔熷氨鏄,濡傛灉
瑕侀噰鐢‥T妯″紡,闇瑕佷竴鐩磖ead/write鐩村埌鍑洪敊涓烘,寰堝浜哄弽鏄犱負浠涔堥噰鐢‥T妯″紡鍙帴鏀朵簡涓閮ㄥ垎鏁版嵁灝卞啀涔熷緱涓嶅埌閫氱煡浜?澶у鍥犱負榪欐牱;鑰孡T
妯″紡鏄彧瑕佹湁鏁版嵁娌℃湁澶勭悊灝變細涓鐩撮氱煡涓嬪幓鐨?
1)瀵逛簬鐩戝惉鍙浜嬩歡鏃?濡傛灉鏄痵ocket鏄洃鍚瑂ocket,閭d箞褰撴湁鏂扮殑涓誨姩榪炴帴鍒版潵涓虹姸鎬佸彂鐢熷彉鍖?瀵逛竴鑸殑socket鑰岃█,鍗忚鏍堜腑鐩稿簲鐨勭紦
鍐插尯鏈夋柊鐨勬暟鎹負鐘舵佸彂鐢熷彉鍖?浣嗘槸,濡傛灉鍦ㄤ竴涓椂闂村悓鏃舵帴鏀朵簡N涓繛鎺?N>1),浣嗘槸鐩戝惉socket鍙猘ccept浜嗕竴涓繛鎺?閭d箞鍏跺畠鏈?
accept鐨勮繛鎺ュ皢涓嶄細鍦‥T妯″紡涓嬬粰鐩戝惉socket鍙戝嚭閫氱煡,姝ゆ椂鐘舵佷笉鍙戠敓鍙樺寲;瀵逛簬涓鑸殑socket,灝卞渚嬪瓙涓岃█,濡傛灉瀵瑰簲鐨勭紦鍐插尯鏈韓
宸茬粡鏈変簡N瀛楄妭鐨勬暟鎹?鑰屽彧鍙栧嚭浜嗗皬浜嶯瀛楄妭鐨勬暟鎹?閭d箞孌嬪瓨鐨勬暟鎹笉浼氶犳垚鐘舵佸彂鐢熷彉鍖?
2)瀵逛簬鐩戝惉鍙啓浜嬩歡鏃?鍚岀悊鍙帹,涓嶅啀璇﹁堪.
鑰屼笉璁烘槸鐩戝惉鍙榪樻槸鍙啓,瀵規柟鍏抽棴socket榪炴帴閮藉皢閫犳垚鐘舵佸彂鐢熷彉鍖?姣斿鍦ㄤ緥瀛愪腑,濡傛灉寮鴻涓柇client鑴氭湰,涔熷氨鏄富鍔ㄤ腑鏂簡socket榪炴帴,閭d箞閮藉皢閫犳垚server绔彂鐢熺姸鎬佺殑鍙樺寲,浠庤宻erver寰楀埌閫氱煡,灝嗗凡緇忓湪鏈柟緙撳啿鍖轟腑鐨勬暟鎹鍑?
鎶婂墠闈㈢殑鎻忚堪鍙互鎬葷粨濡備笅:浠呭綋瀵規柟鐨勫姩浣?鍙戝嚭鏁版嵁,鍏抽棴榪炴帴絳?閫犳垚鐨勪簨浠舵墠鑳藉鑷寸姸鎬佸彂鐢熷彉鍖?鑰屾湰鏂瑰崗璁爤涓凡緇忓鐞嗙殑浜嬩歡(鍖呮嫭鎺ユ敹浜嗗鏂圭殑鏁?
鎹?鎺ユ敹浜嗗鏂圭殑涓誨姩榪炴帴璇鋒眰)騫朵笉鏄犳垚鐘舵佸彂鐢熷彉鍖栫殑蹇呰鏉′歡,鐘舵佸彉鍖栦竴瀹氭槸瀵規柟閫犳垚鐨?鎵浠ュ湪ET妯″紡涓嬬殑,蹇呴』涓鐩村鐞嗗埌鍑洪敊鎴栬呭畬鍏ㄥ鐞嗗畬
姣?鎵嶈兘榪涜涓嬩竴涓姩浣?鍚﹀垯鍙兘浼氬彂鐢熼敊璇?
鍙﹀,浠庤繖涓緥瀛愪腑,涔熷彲浠ラ槓榪頒竴浜涘熀鏈殑緗戠粶緙栫▼姒傚康.棣栧厛,榪炴帴鐨勪袱绔腑,涓绔彂閫佹垚鍔熷茍涓嶄唬琛ㄧ潃瀵規柟涓婂眰搴旂敤紼嬪簭鎺ユ敹鎴愬姛,
灝辨嬁涓婇潰鐨刢lient嫻嬭瘯紼嬪簭鏉ヨ,10瀛楄妭鐨勬暟鎹凡緇忓彂閫佹垚鍔?浣嗘槸涓婂眰鐨剆erver騫舵病鏈夎皟鐢╮ead璇誨彇鏁版嵁,鍥犳鍙戦佹垚鍔熶粎浠呰鏄庝簡鏁版嵁琚
鏂圭殑鍗忚鏍堟帴鏀跺瓨鏀懼湪浜嗙浉搴旂殑buffer涓?鑰屼笂灞傜殑搴旂敤紼嬪簭鏄惁鎺ユ敹浜嗚繖閮ㄥ垎鏁版嵁涓嶅緱鑰岀煡;鍚屾牱鐨?璇誨彇鏁版嵁鏃朵篃鍙唬琛ㄧ潃鏈柟鍗忚鏍堢殑瀵瑰簲
buffer涓湁鏁版嵁鍙,鑰屾鏃舵椂鍊欏湪瀵圭鏄惁鍦ㄥ彂閫佹暟鎹篃涓嶅緱鑰岀煡.
]]>