??xml version="1.0" encoding="utf-8" standalone="yes"?>草草久久久无码国产专区,伊人久久精品影院,日本免费久久久久久久网站http://www.shnenglu.com/tankzhouqiang/category/16141.htmlzh-cnSun, 07 Aug 2011 15:08:24 GMTSun, 07 Aug 2011 15:08:24 GMT60linux RPC 试Q{载)(j)http://www.shnenglu.com/tankzhouqiang/archive/2011/08/07/152718.html周强周强Sun, 07 Aug 2011 08:44:00 GMThttp://www.shnenglu.com/tankzhouqiang/archive/2011/08/07/152718.htmlhttp://www.shnenglu.com/tankzhouqiang/comments/152718.htmlhttp://www.shnenglu.com/tankzhouqiang/archive/2011/08/07/152718.html#Feedback0http://www.shnenglu.com/tankzhouqiang/comments/commentRss/152718.htmlhttp://www.shnenglu.com/tankzhouqiang/services/trackbacks/152718.html转自:
http://www.justwinit.cn/post/3960/


RPC是glibc提供的函数参?q回值封装服? q将装l果通过|络传到服务?
RPC服务端首先要启动portmapper服务.
试一个简单的RPC传输CZ, 先定义一个模板文件test.x

program TESTPROG{
        version VERSION{
                int int_echo(int)=1;
                int get_str_len(string)=2;
                int add ( int, int ) = 3;
        }=1;
}=30000;
内含3个函? 注意其中一个有2个参?
然后可以用rpcgen生成一个Makefile:

rpcgen -a -N test.x

q会(x)生成Makefile, 客户端和服务端的E序, 和函数示?
我们手工修改一下Makefile

# This is a template Makefile generated by rpcgen
# 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服务端的处理函数, 提供3U服?

/*
* 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;
}

客户端test_client.c, 调用q三U服?

/*
* 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);
}
OK, 可以调用make?
生成可执行程序test_server和test_client.
我们启动./test_server, 用rpcinfo看看:

$rpcinfo -p 127.0.0.1
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

正是我们期望?

Add ByQJackxiang
make -f Makefile.test


周强 2011-08-07 16:44 发表评论
]]>
客户/服务器程序设计范?/title><link>http://www.shnenglu.com/tankzhouqiang/archive/2011/04/04/143413.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Mon, 04 Apr 2011 11:38:00 GMT</pubDate><guid>http://www.shnenglu.com/tankzhouqiang/archive/2011/04/04/143413.html</guid><wfw:comment>http://www.shnenglu.com/tankzhouqiang/comments/143413.html</wfw:comment><comments>http://www.shnenglu.com/tankzhouqiang/archive/2011/04/04/143413.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/tankzhouqiang/comments/commentRss/143413.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/tankzhouqiang/services/trackbacks/143413.html</trackback:ping><description><![CDATA[参?nbsp; unix|络~程<br>客户/服务器程序设计范式有<br>Q?QP代服务器Q无q程控制)<br>Q?Qƈ发服务器Q每个客戯求fork 一个子q程<br>Q?Q预先派生子q程Q每个子q程无保护地调用accept<br>Q?Q预先派生子q程Q用文件上锁保护accept<br>Q?Q预先派生子q程Q用线E互斥锁保护acceptQ共享内?<br>Q?Q预先派生子q程Q父q程向子q程传递套接口描述?br>Q?Qƈ发服务器Q每个客戯求创Z个线E?br>Q?Q预先创建线E服务器Q用互斥锁上锁保护accept<br>Q?Q预先创建线E服务器Q由ȝE调用accept.<br><br>试用例 客户创徏5个进E,每个发v500个连接,每个q接写四个字节数?br>                          ȝ用户旉Q秒Q?               ȝpȝ旉Q秒Q?br>Q?Q?                     0.012                                   0.16001<br>Q?Q?                     0.008                                   0.256016<br>Q?Q?                     0.016                                   0.268016<br>Q?Q?                     0.020001                             0.380023<br>Q?Q?                     0.012                                   0.308019<br>Q?Q?                     0.068003                             0.464029<br>Q?Q?                     0.024001                             0.224014<br>Q?Q?                     0.012                                   0.280017<br>Q?Q?                     0.0160001                           0.268016 <br><br> <img src ="http://www.shnenglu.com/tankzhouqiang/aggbug/143413.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/tankzhouqiang/" target="_blank">周强</a> 2011-04-04 19:38 <a href="http://www.shnenglu.com/tankzhouqiang/archive/2011/04/04/143413.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下飞鸽传书实?/title><link>http://www.shnenglu.com/tankzhouqiang/archive/2011/03/15/141915.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Tue, 15 Mar 2011 13:57:00 GMT</pubDate><guid>http://www.shnenglu.com/tankzhouqiang/archive/2011/03/15/141915.html</guid><wfw:comment>http://www.shnenglu.com/tankzhouqiang/comments/141915.html</wfw:comment><comments>http://www.shnenglu.com/tankzhouqiang/archive/2011/03/15/141915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/tankzhouqiang/comments/commentRss/141915.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/tankzhouqiang/services/trackbacks/141915.html</trackback:ping><description><![CDATA[<!--[if !mso]> <style> v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><!--[if gte mso 9]><xml> <w:worddocument> <w:view>Normal</w:view> <w:zoom>0</w:zoom> <w:trackmoves/> <w:trackformatting/> <w:punctuationkerning/> <w:drawinggridverticalspacing>7.8 ?/w:drawinggridverticalspacing> <w:displayhorizontaldrawinggridevery>0</w:displayhorizontaldrawinggridevery> <w:displayverticaldrawinggridevery>2</w:displayverticaldrawinggridevery> <w:validateagainstschemas/> <w:saveifxmlinvalid>false</w:saveifxmlinvalid> <w:ignoremixedcontent>false</w:ignoremixedcontent> <w:alwaysshowplaceholdertext>false</w:alwaysshowplaceholdertext> <w:donotpromoteqf/> <w:lidthemeother>EN-US</w:lidthemeother> <w:lidthemeasian>ZH-CN</w:lidthemeasian> <w:lidthemecomplexscript>X-NONE</w:lidthemecomplexscript> <w:compatibility> <w:spaceforul/> <w:balancesinglebytedoublebytewidth/> <w:donotleavebackslashalone/> <w:ultrailspace/> <w:donotexpandshiftreturn/> <w:adjustlineheightintable/> <w:breakwrappedtables/> <w:snaptogridincell/> <w:wraptextwithpunct/> <w:useasianbreakrules/> <w:dontgrowautofit/> <w:splitpgbreakandparamark/> <w:dontvertaligncellwithsp/> <w:dontbreakconstrainedforcedtables/> <w:dontvertalignintxbx/> <w:word11kerningpairs/> <w:cachedcolbalance/> <w:usefelayout/> </w:compatibility> <w:browserlevel>MicrosoftInternetExplorer4</w:browserlevel> <m:mathpr> <m:mathfont m:val="Cambria Math"/> <m:brkbin m:val="before"/> <m:brkbinsub m:val="--"/> <m:smallfrac m:val="off"/> <m:dispdef/> <m:lmargin m:val="0"/> <m:rmargin m:val="0"/> <m:defjc m:val="centerGroup"/> <m:wrapindent m:val="1440"/> <m:intlim m:val="subSup"/> <m:narylim m:val="undOvr"/> </m:mathpr></w:worddocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:latentstyles deflockedstate="false" defunhidewhenused="true" DefSemiHidden="true" defqformat="false" defpriority="99" LatentStyleCount="267"> <w:lsdexception locked="false" priority="0" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Normal"/> <w:lsdexception locked="false" priority="9" semihidden="false" UnhideWhenUsed="false" qformat="true" name="heading 1"/> <w:lsdexception locked="false" priority="9" qformat="true" name="heading 2"/> <w:lsdexception locked="false" priority="9" qformat="true" name="heading 3"/> <w:lsdexception locked="false" priority="9" qformat="true" name="heading 4"/> <w:lsdexception locked="false" priority="9" qformat="true" name="heading 5"/> <w:lsdexception locked="false" priority="9" qformat="true" name="heading 6"/> <w:lsdexception locked="false" priority="9" qformat="true" name="heading 7"/> <w:lsdexception locked="false" priority="9" qformat="true" name="heading 8"/> <w:lsdexception locked="false" priority="9" qformat="true" name="heading 9"/> <w:lsdexception locked="false" priority="39" name="toc 1"/> <w:lsdexception locked="false" priority="39" name="toc 2"/> <w:lsdexception locked="false" priority="39" name="toc 3"/> <w:lsdexception locked="false" priority="39" name="toc 4"/> <w:lsdexception locked="false" priority="39" name="toc 5"/> <w:lsdexception locked="false" priority="39" name="toc 6"/> <w:lsdexception locked="false" priority="39" name="toc 7"/> <w:lsdexception locked="false" priority="39" name="toc 8"/> <w:lsdexception locked="false" priority="39" name="toc 9"/> <w:lsdexception locked="false" priority="35" qformat="true" name="caption"/> <w:lsdexception locked="false" priority="10" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Title"/> <w:lsdexception locked="false" priority="1" name="Default Paragraph Font"/> <w:lsdexception locked="false" priority="11" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Subtitle"/> <w:lsdexception locked="false" priority="22" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Strong"/> <w:lsdexception locked="false" priority="20" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Emphasis"/> <w:lsdexception locked="false" priority="59" semihidden="false" UnhideWhenUsed="false" name="Table Grid"/> <w:lsdexception locked="false" unhidewhenused="false" name="Placeholder Text"/> <w:lsdexception locked="false" priority="1" semihidden="false" UnhideWhenUsed="false" qformat="true" name="No Spacing"/> <w:lsdexception locked="false" priority="60" semihidden="false" UnhideWhenUsed="false" name="Light Shading"/> <w:lsdexception locked="false" priority="61" semihidden="false" UnhideWhenUsed="false" name="Light List"/> <w:lsdexception locked="false" priority="62" semihidden="false" UnhideWhenUsed="false" name="Light Grid"/> <w:lsdexception locked="false" priority="63" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 1"/> <w:lsdexception locked="false" priority="64" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 2"/> <w:lsdexception locked="false" priority="65" semihidden="false" UnhideWhenUsed="false" name="Medium List 1"/> <w:lsdexception locked="false" priority="66" semihidden="false" UnhideWhenUsed="false" name="Medium List 2"/> <w:lsdexception locked="false" priority="67" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 1"/> <w:lsdexception locked="false" priority="68" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 2"/> <w:lsdexception locked="false" priority="69" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 3"/> <w:lsdexception locked="false" priority="70" semihidden="false" UnhideWhenUsed="false" name="Dark List"/> <w:lsdexception locked="false" priority="71" semihidden="false" UnhideWhenUsed="false" name="Colorful Shading"/> <w:lsdexception locked="false" priority="72" semihidden="false" UnhideWhenUsed="false" name="Colorful List"/> <w:lsdexception locked="false" priority="73" semihidden="false" UnhideWhenUsed="false" name="Colorful Grid"/> <w:lsdexception locked="false" priority="60" semihidden="false" UnhideWhenUsed="false" name="Light Shading Accent 1"/> <w:lsdexception locked="false" priority="61" semihidden="false" UnhideWhenUsed="false" name="Light List Accent 1"/> <w:lsdexception locked="false" priority="62" semihidden="false" UnhideWhenUsed="false" name="Light Grid Accent 1"/> <w:lsdexception locked="false" priority="63" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 1 Accent 1"/> <w:lsdexception locked="false" priority="64" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 2 Accent 1"/> <w:lsdexception locked="false" priority="65" semihidden="false" UnhideWhenUsed="false" name="Medium List 1 Accent 1"/> <w:lsdexception locked="false" unhidewhenused="false" name="Revision"/> <w:lsdexception locked="false" priority="34" semihidden="false" UnhideWhenUsed="false" qformat="true" name="List Paragraph"/> <w:lsdexception locked="false" priority="29" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Quote"/> <w:lsdexception locked="false" priority="30" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Intense Quote"/> <w:lsdexception locked="false" priority="66" semihidden="false" UnhideWhenUsed="false" name="Medium List 2 Accent 1"/> <w:lsdexception locked="false" priority="67" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 1 Accent 1"/> <w:lsdexception locked="false" priority="68" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 2 Accent 1"/> <w:lsdexception locked="false" priority="69" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 3 Accent 1"/> <w:lsdexception locked="false" priority="70" semihidden="false" UnhideWhenUsed="false" name="Dark List Accent 1"/> <w:lsdexception locked="false" priority="71" semihidden="false" UnhideWhenUsed="false" name="Colorful Shading Accent 1"/> <w:lsdexception locked="false" priority="72" semihidden="false" UnhideWhenUsed="false" name="Colorful List Accent 1"/> <w:lsdexception locked="false" priority="73" semihidden="false" UnhideWhenUsed="false" name="Colorful Grid Accent 1"/> <w:lsdexception locked="false" priority="60" semihidden="false" UnhideWhenUsed="false" name="Light Shading Accent 2"/> <w:lsdexception locked="false" priority="61" semihidden="false" UnhideWhenUsed="false" name="Light List Accent 2"/> <w:lsdexception locked="false" priority="62" semihidden="false" UnhideWhenUsed="false" name="Light Grid Accent 2"/> <w:lsdexception locked="false" priority="63" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 1 Accent 2"/> <w:lsdexception locked="false" priority="64" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 2 Accent 2"/> <w:lsdexception locked="false" priority="65" semihidden="false" UnhideWhenUsed="false" name="Medium List 1 Accent 2"/> <w:lsdexception locked="false" priority="66" semihidden="false" UnhideWhenUsed="false" name="Medium List 2 Accent 2"/> <w:lsdexception locked="false" priority="67" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 1 Accent 2"/> <w:lsdexception locked="false" priority="68" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 2 Accent 2"/> <w:lsdexception locked="false" priority="69" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 3 Accent 2"/> <w:lsdexception locked="false" priority="70" semihidden="false" UnhideWhenUsed="false" name="Dark List Accent 2"/> <w:lsdexception locked="false" priority="71" semihidden="false" UnhideWhenUsed="false" name="Colorful Shading Accent 2"/> <w:lsdexception locked="false" priority="72" semihidden="false" UnhideWhenUsed="false" name="Colorful List Accent 2"/> <w:lsdexception locked="false" priority="73" semihidden="false" UnhideWhenUsed="false" name="Colorful Grid Accent 2"/> <w:lsdexception locked="false" priority="60" semihidden="false" UnhideWhenUsed="false" name="Light Shading Accent 3"/> <w:lsdexception locked="false" priority="61" semihidden="false" UnhideWhenUsed="false" name="Light List Accent 3"/> <w:lsdexception locked="false" priority="62" semihidden="false" UnhideWhenUsed="false" name="Light Grid Accent 3"/> <w:lsdexception locked="false" priority="63" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 1 Accent 3"/> <w:lsdexception locked="false" priority="64" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 2 Accent 3"/> <w:lsdexception locked="false" priority="65" semihidden="false" UnhideWhenUsed="false" name="Medium List 1 Accent 3"/> <w:lsdexception locked="false" priority="66" semihidden="false" UnhideWhenUsed="false" name="Medium List 2 Accent 3"/> <w:lsdexception locked="false" priority="67" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 1 Accent 3"/> <w:lsdexception locked="false" priority="68" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 2 Accent 3"/> <w:lsdexception locked="false" priority="69" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 3 Accent 3"/> <w:lsdexception locked="false" priority="70" semihidden="false" UnhideWhenUsed="false" name="Dark List Accent 3"/> <w:lsdexception locked="false" priority="71" semihidden="false" UnhideWhenUsed="false" name="Colorful Shading Accent 3"/> <w:lsdexception locked="false" priority="72" semihidden="false" UnhideWhenUsed="false" name="Colorful List Accent 3"/> <w:lsdexception locked="false" priority="73" semihidden="false" UnhideWhenUsed="false" name="Colorful Grid Accent 3"/> <w:lsdexception locked="false" priority="60" semihidden="false" UnhideWhenUsed="false" name="Light Shading Accent 4"/> <w:lsdexception locked="false" priority="61" semihidden="false" UnhideWhenUsed="false" name="Light List Accent 4"/> <w:lsdexception locked="false" priority="62" semihidden="false" UnhideWhenUsed="false" name="Light Grid Accent 4"/> <w:lsdexception locked="false" priority="63" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 1 Accent 4"/> <w:lsdexception locked="false" priority="64" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 2 Accent 4"/> <w:lsdexception locked="false" priority="65" semihidden="false" UnhideWhenUsed="false" name="Medium List 1 Accent 4"/> <w:lsdexception locked="false" priority="66" semihidden="false" UnhideWhenUsed="false" name="Medium List 2 Accent 4"/> <w:lsdexception locked="false" priority="67" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 1 Accent 4"/> <w:lsdexception locked="false" priority="68" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 2 Accent 4"/> <w:lsdexception locked="false" priority="69" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 3 Accent 4"/> <w:lsdexception locked="false" priority="70" semihidden="false" UnhideWhenUsed="false" name="Dark List Accent 4"/> <w:lsdexception locked="false" priority="71" semihidden="false" UnhideWhenUsed="false" name="Colorful Shading Accent 4"/> <w:lsdexception locked="false" priority="72" semihidden="false" UnhideWhenUsed="false" name="Colorful List Accent 4"/> <w:lsdexception locked="false" priority="73" semihidden="false" UnhideWhenUsed="false" name="Colorful Grid Accent 4"/> <w:lsdexception locked="false" priority="60" semihidden="false" UnhideWhenUsed="false" name="Light Shading Accent 5"/> <w:lsdexception locked="false" priority="61" semihidden="false" UnhideWhenUsed="false" name="Light List Accent 5"/> <w:lsdexception locked="false" priority="62" semihidden="false" UnhideWhenUsed="false" name="Light Grid Accent 5"/> <w:lsdexception locked="false" priority="63" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 1 Accent 5"/> <w:lsdexception locked="false" priority="64" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 2 Accent 5"/> <w:lsdexception locked="false" priority="65" semihidden="false" UnhideWhenUsed="false" name="Medium List 1 Accent 5"/> <w:lsdexception locked="false" priority="66" semihidden="false" UnhideWhenUsed="false" name="Medium List 2 Accent 5"/> <w:lsdexception locked="false" priority="67" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 1 Accent 5"/> <w:lsdexception locked="false" priority="68" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 2 Accent 5"/> <w:lsdexception locked="false" priority="69" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 3 Accent 5"/> <w:lsdexception locked="false" priority="70" semihidden="false" UnhideWhenUsed="false" name="Dark List Accent 5"/> <w:lsdexception locked="false" priority="71" semihidden="false" UnhideWhenUsed="false" name="Colorful Shading Accent 5"/> <w:lsdexception locked="false" priority="72" semihidden="false" UnhideWhenUsed="false" name="Colorful List Accent 5"/> <w:lsdexception locked="false" priority="73" semihidden="false" UnhideWhenUsed="false" name="Colorful Grid Accent 5"/> <w:lsdexception locked="false" priority="60" semihidden="false" UnhideWhenUsed="false" name="Light Shading Accent 6"/> <w:lsdexception locked="false" priority="61" semihidden="false" UnhideWhenUsed="false" name="Light List Accent 6"/> <w:lsdexception locked="false" priority="62" semihidden="false" UnhideWhenUsed="false" name="Light Grid Accent 6"/> <w:lsdexception locked="false" priority="63" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 1 Accent 6"/> <w:lsdexception locked="false" priority="64" semihidden="false" UnhideWhenUsed="false" name="Medium Shading 2 Accent 6"/> <w:lsdexception locked="false" priority="65" semihidden="false" UnhideWhenUsed="false" name="Medium List 1 Accent 6"/> <w:lsdexception locked="false" priority="66" semihidden="false" UnhideWhenUsed="false" name="Medium List 2 Accent 6"/> <w:lsdexception locked="false" priority="67" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 1 Accent 6"/> <w:lsdexception locked="false" priority="68" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 2 Accent 6"/> <w:lsdexception locked="false" priority="69" semihidden="false" UnhideWhenUsed="false" name="Medium Grid 3 Accent 6"/> <w:lsdexception locked="false" priority="70" semihidden="false" UnhideWhenUsed="false" name="Dark List Accent 6"/> <w:lsdexception locked="false" priority="71" semihidden="false" UnhideWhenUsed="false" name="Colorful Shading Accent 6"/> <w:lsdexception locked="false" priority="72" semihidden="false" UnhideWhenUsed="false" name="Colorful List Accent 6"/> <w:lsdexception locked="false" priority="73" semihidden="false" UnhideWhenUsed="false" name="Colorful Grid Accent 6"/> <w:lsdexception locked="false" priority="19" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Subtle Emphasis"/> <w:lsdexception locked="false" priority="21" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Intense Emphasis"/> <w:lsdexception locked="false" priority="31" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Subtle Reference"/> <w:lsdexception locked="false" priority="32" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Intense Reference"/> <w:lsdexception locked="false" priority="33" semihidden="false" UnhideWhenUsed="false" qformat="true" name="Book Title"/> <w:lsdexception locked="false" priority="37" name="Bibliography"/> <w:lsdexception locked="false" priority="39" qformat="true" name="TOC Heading"/> </w:latentstyles> </xml><![endif]--><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表? mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;} </style> <![endif]--> <p class="MsoPlainText"><span lang="EN-US">Linux </span><span>下飞鸽传书设计实?span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US">1.</span><span>pȝ功能<span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span>Ҏ(gu)飞鸽传书协议?span lang="EN-US"> linux </span>下实现飞鸽传输程?span lang="EN-US">,</span>q且?span lang="EN-US"> windows </span>下飞鸽兼宏V具体功能模块包括用户上U?span lang="EN-US">,</span>下线<span lang="EN-US">,</span>h查看在线用户<span lang="EN-US">,</span>收发消息<span lang="EN-US">,</span>传送文?span lang="EN-US">/</span>文g夹功能模块?span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">2.</span><span>具体实现<span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US">2.1 </span><span>关键数据l构<span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US">/*</span><span>命o(h)的结?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">typedef struct _command</span></p> <p class="MsoPlainText"><span lang="EN-US"> {</span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>int version;/*</span><span>命o(h)的版?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>int seq;/*</span><span>包编?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>char srcName[100];/*</span><span>发送者姓?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>char srcHost[100];/*</span><span>发送者主机名<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>int flag;/*</span><span>命o(h)<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>char addtion[100];/*</span><span>附加字段<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"> }command;</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">/*</span><span>在线用户信息<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">typedef struct _userInfo</span></p> <p class="MsoPlainText"><span lang="EN-US">{</span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>char name[MAXLINE];<span>     </span>/*</span><span>姓名<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>char host[MAXLINE];<span>         </span>/*</span><span>L?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>char group[MAXLINE];<span>        </span>/*</span><span>所在的l名<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>struct sockaddr_in addr;<span>        </span>/*</span><span>地址信息<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>struct _userInfo next;<span>      </span>/*</span><span>链表中下一?span lang="EN-US">*/ </span></span></p> <p class="MsoPlainText"><span lang="EN-US">}userInfo;</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">/*</span><span>在线用户列表<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">typedef struct _uList</span></p> <p class="MsoPlainText"><span lang="EN-US">{</span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>userInfo *userListHead;<span>     </span>/*</span><span>链表?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>userInfo userListTail;<span>      </span>/*</span><span>链表?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">}uList;</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">/*</span><span>消息队列<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">typedef struct _mesList</span></p> <p class="MsoPlainText"><span lang="EN-US">{</span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>command *mesHead;</span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span>command *mesTail;</span></p> <p class="MsoPlainText"><span lang="EN-US">}mesList;</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">2.2 </span><span>E序主要l构<span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span>本程序主要采用多U程l构<span lang="EN-US">,</span>分ؓ(f)<span lang="EN-US"> receive(</span>接收消息<span lang="EN-US">), process(</span>处理收到的消?span lang="EN-US">), sendData(</span>发送文?span lang="EN-US">) </span>三个子线E。线E间通信互斥锁与<span lang="EN-US"> Posix </span>信号量进行通信?span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US"><br></span><span lang="EN-US"></span></p> <p class="MsoPlainText"><span lang="EN-US">2.3 </span><span>函数接口<span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US">(1) /*</span><span>从文件描q符<span lang="EN-US">fd</span>中读?span lang="EN-US">count</span>个字W存?span lang="EN-US">buf</span>?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span> </span>ssize_t readn(int fd,void *buf,size_t count)</span><span>Q?span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(2) /*</span><span>?span lang="EN-US">buf</span>所指向的存储区中的<span lang="EN-US">len</span>个字W吸入文件描q符<span lang="EN-US">fd</span>?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span> </span>ssize_t writen(int fd,char *buf,int len);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(3) /*</span><span>用于字符串{?span lang="EN-US">,</span>|络传输中用<span lang="EN-US">gb2312</span>~码Q?span lang="EN-US">linux</span>?span lang="EN-US">gtk</span>?span lang="EN-US">utf-8</span>~码Q需要进行{?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span> </span>int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(4) /*</span><span>在用户链表中加入新用户信息,加入成功q回<span lang="EN-US">1</span>Q否则返?span lang="EN-US">0,</span>使用<span lang="EN-US">userInfoMutex</span>q行U程间通信控制<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>  </span>int pushBack(uList *list,userInfo user);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(5) /*</span><span>在用户链表中删除指定地址信息的用P删除成功后返?span lang="EN-US">1</span>Q否则返?span lang="EN-US">0</span>Q?span lang="EN-US">userInfoMutex</span>q行U程间控?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span>  </span>int delUser(uList *list, struct sockaddr_in addr);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(6) /*</span><span>判断该用h否已l存在,已经存在则返?span lang="EN-US">1</span>Q否则返?span lang="EN-US">0,</span>使用<span lang="EN-US">userInfoMutex</span>q行U程间控?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">int isExist(uList *list,struct sockaddr_in addr);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(7)</span><span>清空用户链表Q释攄_(d)用于用户退出和用户h旉攄?span lang="EN-US">,</span>使用<span lang="EN-US">userInfoMutex</span>q行U程间控?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">int destroyList(uList *list);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(8)/*</span><span>创徏命o(h)?span lang="EN-US">,com</span>q回的命令字<span lang="EN-US">,flag </span>为消息标?span lang="EN-US">,addtion </span>为附加标?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void createCmd(command & com,int flag,char addtion[])</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(9)/*</span><span>发送消息,<span lang="EN-US">com</span>发送的消息Q?span lang="EN-US">servaddr</span>发送的地址Q?span lang="EN-US">attach</span>为文仉件信?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">void sendCmd(command com, struct sockaddr_in servaddr,char attach[]);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(10) /*</span><span>把收到的消息加入到消息队列中<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void addMes(mesList *mHead,command cmd);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(11) /*</span><span>把消息队列中头部的节Ҏ(gu)息提取出来用于处?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">int delMes(mesList *mHead,command *cmd);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(12)/*</span><span>初始化操作,飞鸽d时初始化消息链表Q用户链表,信号量,套接字信?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span> </span>void init();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(13)/*</span><span>d操作<span lang="EN-US">,</span>发送用户上U消?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void login();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(14)/*</span><span>解析收到的消息命令,提取各个字段<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span> </span>int analysisCmd(command *cmd,char *buf);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(15) /*</span><span>接收消息U程处理函数<span lang="EN-US">,</span>收到的消息加入消息队列中,通过信号?span lang="EN-US">waitNoFull</span>?span lang="EN-US">waitNoEmpty</span>和消息处理线E进行通信。消息队列用<span lang="EN-US">mesMutex</span>与其他线E进行通信Q保证消息队列的正确?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US"><span> </span>void *receive(void *arg);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(16)/*gtk</span><span>界面中显C在U用户信?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void showUser(uList *list);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(17)/*</span><span>?span lang="EN-US">gtk</span>界面中显C消?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void showMessage(char *message);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(18)/*</span><span>昄收到的信?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void showRecvMessage(char *host,char *message);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(19)/*</span><span>分析文g的信息,提取有用的字D?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void fileAnalysis(char *recv,int *fNum,char *fName,int *fSize,int *fTime,int *fType);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(20) /*</span><span>保存收到的单个文?span lang="EN-US">,saveName</span>Z存的文g?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void saveSignalFile(char *saveName);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(21)/*</span><span>分析目录附gQ获得目录文件的文g名,文g大小Q文件类?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void getDirInfo(char *recv,char *fName,int *fSize,int *fType);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(22) /*</span><span>保存目录<span lang="EN-US">,saveName</span>保存的目?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void saveDir(char *saveName);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(23)/*</span><span>保存文g<span lang="EN-US">,recvType=1</span>Z存文Ӟ<span lang="EN-US">recvType=2</span>Z存的目录<span lang="EN-US">,</span>使用<span lang="EN-US">fileMutex</span>来设|互斥?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void saveFile();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(24)/*</span><span>收到单个文g<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void receiveSignalFile(char *recvFileName);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(25)/*</span><span>收到单个目录<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void receiveDir(char *recvDirName);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(26)/*</span><span>接收文g<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void receiveFile(command cmd);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(27)/*</span><span>信号处理U程<span lang="EN-US">,</span>从消息队列中取出消息q行处理<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void *process(void *arg);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(28)/*</span><span>发送消?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">int sendMes();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(29) /*</span><span>文件名q行转换<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">char *transName(char *fileName);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(30)/*</span><span>发送文?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void sendFile();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(31)/*</span><span>发送文件夹<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void sendDir();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(32)/*</span><span>用户点击h<span lang="EN-US">,</span>h在线用户<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void refresh();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(33) /*</span><span>用户退?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void quit();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(34)/*</span><span>传输文gҎ(gu)据,递归函数<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void transferDir(int fd,char *dir);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(35)/*</span><span>监听<span lang="EN-US">TCP</span>套接口,发送文件与文g夹线E?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">void *sendData(void *arg);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(36)/*</span><span>创徏菜单<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">static void create_popup_menu(GtkWidget *menu,GtkWidget *view);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(37)/*</span><span>叛_选中<span lang="EN-US">treeview,</span>昄传送文件与文g夹菜?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">static gboolean showTreeView(GtkWidget *eventBox,GdkEventButton *event,GtkWidget *menu);</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(38)/*</span><span>选择要发送的文g<span lang="EN-US"> */</span></span></p> <p class="MsoPlainText"><span lang="EN-US">static void selectFile();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(39)/*</span><span>选择要发送的文g?span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">static void selectDir();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">(40)/*</span><span>选择要保存的文g名或文g夹名<span lang="EN-US">*/</span></span></p> <p class="MsoPlainText"><span lang="EN-US">static void selectSaveFile();</span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US">3.</span><span>ȝ<span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US"><span>    </span></span><span>实现?span lang="EN-US">linux</span>下飞鸽传书的基本功能Qƈ且能?span lang="EN-US">window</span>下飞鸽进行通信Q传文g。熟(zhn)了(jin)<span lang="EN-US">linux</span>下网l编E,多线E编E及(qing)U程间通信Q主要用C号量与互斥锁Q。但加密解密那块没有完成Q程序结构不是很好,界面做得太差。有I应该看看设计模?span lang="EN-US">.</span></span></p> <p class="MsoPlainText">界面截图Q界面比较垃?Q?/p> <p class="MsoPlainText"><img src="http://www.shnenglu.com/images/cppblog_com/tankzhouqiang/Screenshot.png" border="0"><br><span><span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span><span lang="EN-US">附:(x)</span></span></p> <p class="MsoPlainText"><span><span lang="EN-US">飞鸽协议Q?http://bbs.chinaunix.net/viewthread.php?tid=1015775<br></span></span></p> <p class="MsoPlainText"><span> <span lang="EN-US"></span></span></p> <p class="MsoPlainText"><span lang="EN-US"><br></span><span lang="EN-US"></span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoPlainText"><span lang="EN-US"> </span></p> <p class="MsoNormal"><span lang="EN-US"> </span></p><img src ="http://www.shnenglu.com/tankzhouqiang/aggbug/141915.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/tankzhouqiang/" target="_blank">周强</a> 2011-03-15 21:57 <a href="http://www.shnenglu.com/tankzhouqiang/archive/2011/03/15/141915.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>epoll模型Q{载)(j)http://www.shnenglu.com/tankzhouqiang/archive/2011/03/02/140973.html周强周强Wed, 02 Mar 2011 04:23:00 GMThttp://www.shnenglu.com/tankzhouqiang/archive/2011/03/02/140973.htmlhttp://www.shnenglu.com/tankzhouqiang/comments/140973.htmlhttp://www.shnenglu.com/tankzhouqiang/archive/2011/03/02/140973.html#Feedback0http://www.shnenglu.com/tankzhouqiang/comments/commentRss/140973.htmlhttp://www.shnenglu.com/tankzhouqiang/services/trackbacks/140973.htmlepoll_N

在linux的网l编E中Q很长的旉都在使用select来做事g触发。在linux新的内核中,有了(jin)一U替换它的机Ӟ是epoll?br> 相比于selectQepoll最大的好处在于它不?x)随着监听fd数目的增长而降低效率。因为在内核中的select实现中,它是采用轮询来处理的Q轮询的fd数目多Q自然耗时多。ƈ且,在linux/posix_types.h头文件有q样的声明:(x)
#define __FD_SETSIZE    1024
表示select最多同时监?024个fdQ当?dng)可以通过修改头文件再重编译内核来扩大q个数目Q但q似乎ƈ不治本?br>
epoll的接口非常简单,一共就三个函数Q?br> 1. int epoll_create(int size);
? Z个epoll的句柄,size用来告诉内核q个监听的数目一共有多大。这个参C同于select()中的W一个参敎ͼl出最大监听的fd+1的倹{? 需要注意的是,当创建好epoll句柄后,它就是会(x)占用一个fd|在linux下如果查?proc/q程id/fd/Q是能够看到q个fd的,所以在 使用完epoll后,必须调用close()关闭Q否则可能导致fd被耗尽?br>

2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll的事件注册函敎ͼ它不同与select()是在监听事g时告诉内核要监听什么类型的事gQ而是在这里先注册要监听的事gcd。第一个参数是epoll_create()的返回|W二个参数表C动作,用三个宏来表C:(x)
EPOLL_CTL_ADDQ注册新的fd到epfd中;
EPOLL_CTL_MODQ修改已l注册的fd的监听事Ӟ
EPOLL_CTL_DELQ从epfd中删除一个fdQ?br> W三个参数是需要监听的fdQ第四个参数是告诉内栔R要监听什么事Qstruct epoll_eventl构如下Q?br> struct epoll_event {
  __uint32_t events;  /* Epoll events */
  epoll_data_t data;  /* User data variable */
};

events可以是以下几个宏的集合:(x)
EPOLLIN Q表C对应的文g描述W可以读Q包括对端SOCKET正常关闭Q;
EPOLLOUTQ表C对应的文g描述W可以写Q?br> EPOLLPRIQ表C对应的文g描述W有紧急的数据可读Q这里应该表C有带外数据到来Q;
EPOLLERRQ表C对应的文g描述W发生错误;
EPOLLHUPQ表C对应的文g描述W被挂断Q?br> EPOLLETQ?EPOLL设ؓ(f)边缘触发(Edge Triggered)模式Q这是相对于水^触发(Level Triggered)来说的?br> EPOLLONESHOTQ只监听一ơ事Ӟ当监听完q次事g之后Q如果还需要l监听这个socket的话Q需要再ơ把q个socket加入到EPOLL队列?br>

3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
{? 待事件的产生Q类gselect()调用。参数events用来从内核得C件的集合Qmaxevents告之内核q个events有多大,q个 maxevents的g能大于创建epoll_create()时的sizeQ参数timeout是超时时_(d)毫秒Q??x)立卌回?1不定Q也? 说法说是怹dQ。该函数q回需要处理的事g数目Q如q回0表示已超时?br>
--------------------------------------------------------------------------------------------

从man手册中,得到ET和LT的具体描q如?br>
EPOLL事g有两U模型:(x)
Edge Triggered (ET)
Level Triggered (LT)

假如有这样一个例子:(x)
1. 我们已经把一个用来从道中读取数据的文g句柄(RFD)d到epoll描述W?br> 2. q个时候从道的另一端被写入?KB的数?br> 3. 调用epoll_wait(2)Qƈ且它?x)返回RFDQ说明它已经准备好读取操?br> 4. 然后我们d?KB的数?br> 5. 调用epoll_wait(2)......

Edge Triggered 工作模式Q?br> ? 果我们在W?步将RFDd到epoll描述W的时候用了(jin)EPOLLET标志Q那么在W?步调用epoll_wait(2)之后有可能?x)挂P因ؓ(f)? 余的数据q存在于文g的输入缓冲区内,而且数据发出端还在等待一个针对已l发出数据的反馈信息。只有在监视的文件句柄上发生?jin)某个事件的时?ET 工作模式才会(x)汇报事g。因此在W?步的时候,调用者可能会(x)攑ּ{待仍在存在于文件输入缓冲区内的剩余数据。在上面的例子中Q会(x)有一个事件生在RFD句柄 上,因ؓ(f)在第2步执行了(jin)一个写操作Q然后,事g会(x)在第3步被销毁。因为第4步的d操作没有ȝ文g输入~冲区内的数据,因此我们在第5步调? epoll_wait(2)完成后,是否挂v是不定的。epoll工作在ET模式的时候,必须使用非阻塞套接口Q以避免׃一个文件句柄的d?d 写操作把处理多个文g描述W的d饿死。最好以下面的方式调用ET模式的epoll接口Q在后面?x)介l避免可能的~陷?br>    i    Z非阻塞文件句?br>    ii   只有当read(2)或者write(2)q回EAGAIN时才需要挂P{待?span style="font-weight: bold; color: #0001ff;">但这q不是说每次read()旉需要@环读Q直到读C生一个EAGAIN才认为此ơ事件处理完成,当read()q回的读到的数据长度于h的数据长度时Q就可以定此时~冲中已没有数据?jin),也就可以认?f)此事M件已处理完成?/span>

Level Triggered 工作模式
? 反的Q以LT方式调用epoll接口的时候,它就相当于一个速度比较快的poll(2)Qƈ且无论后面的数据是否被用,因此他们h同样的职能。因为即 使用ET模式的epollQ在收到多个chunk的数据的时候仍然会(x)产生多个事g。调用者可以设定EPOLLONESHOT标志Q在 epoll_wait(2)收到事g后epoll?x)与事g兌的文件句柄从epoll描述W中止掉。因此当EPOLLONESHOT讑֮后,使用带有 EPOLL_CTL_MOD标志的epoll_ctl(2)处理文g句柄成用者必M的事情?br>

然后详细解释ET, LT:

LT(level triggered)是缺省的工作方式Qƈ且同时支持block和no-block socket.在这U做法中Q内核告诉你一个文件描q符是否qA?jin),然后你可以对q个qA的fdq行IO操作。如果你不作M操作Q内核还是会(x)l箋通知? 的,所以,q种模式~程出错误可能性要一炏V传l的select/poll都是q种模型的代表.

ET(edge-triggered) 是高速工作方式,只支持no-block socket。在q种模式下,当描q符从未qA变ؓ(f)qAӞ内核通过epoll告诉你。然后它?x)假设你知道文g描述W已l就l,q且不会(x)再ؓ(f)那个文g描述 W发送更多的qA通知Q直C做了(jin)某些操作D那个文g描述W不再ؓ(f)qA状态了(jin)(比如Q你在发送,接收或者接收请求,或者发送接收的数据于一定量时导? ?jin)一个EWOULDBLOCK 错误Q。但是请注意Q如果一直不对这个fd作IO操作(从而导致它再次变成未就l?Q内怸?x)发送更多的通知(only once),不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark认Q这句话不理解)(j)?/span>

? 许多试中我们会(x)看到如果没有大量的idle -connection或者dead-connectionQepoll的效率ƈ不会(x)比select/poll高很多,但是当我们遇到大量的idle- connection(例如WAN环境中存在大量的慢速连?Q就?x)发现epoll的效率大大高于select/poll。(未测试)(j)



另外Q当使用epoll的ET模型来工作时Q当产生?jin)一个EPOLLIN事g后,
L据的时候需要考虑的是当recv()q回的大如果等于请求的大小Q那么很有可能是~冲有数据未dQ也意味着该次事gq没有处理完Q所以还需要再ơ读?/span> Q?br> while(rs)
{
  buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);
  if(buflen < 0)
  {
    // ׃是非d的模?所以当errno为EAGAIN?表示当前~冲区已无数据可?br>     // 在这里就当作是该ơ事件已处理?
    if(errno == EAGAIN)
     break;
    else
     return;
   }
   else if(buflen == 0)
   {
     // q里表示对端的socket已正常关?
   }
   if(buflen == sizeof(buf)
     rs = 1;   // 需要再ơ读?/span>
   else
     rs = 0;
}


q? 有,假如发送端量大于接收端的量(意思是epoll所在的E序L转发的socket要快),׃是非d的socket,那么send()函数虽然 q回,但实际缓冲区的数据ƈ未真正发l接收端,q样不断的读和发Q当~冲区满后会(x)产生EAGAIN错误(参考man send),同时,不理?x)这ơ请求发送的数据.所?需要封装socket_send()的函数用来处理这U情?该函C(x)量数据写完再q回Q返? -1表示出错。在socket_send()内部,当写~冲已满(send()q回-1,且errno为EAGAIN),那么?x)等待后再重?q种方式q? 不很完美,在理Z可能?x)长旉的阻塞在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)
    {
      // 当send收到信号?可以l箋?但这里返?1.
      if(errno == EINTR)
        return -1;

      // 当socket是非d?如返回此错误,表示写缓冲队列已?
      // 在这里做延时后再重试.
      if(errno == EAGAIN)
      {
        usleep(1000);
        continue;
      }

      return -1;
    }

    if((size_t)tmp == total)
      return buflen;

    total -= tmp;
    p += tmp;
  }

  return tmp;
}



周强 2011-03-02 12:23 发表评论
]]>
epoll模型实例Q{载)(j)http://www.shnenglu.com/tankzhouqiang/archive/2011/03/02/140972.html周强周强Wed, 02 Mar 2011 04:22:00 GMThttp://www.shnenglu.com/tankzhouqiang/archive/2011/03/02/140972.htmlhttp://www.shnenglu.com/tankzhouqiang/comments/140972.htmlhttp://www.shnenglu.com/tankzhouqiang/archive/2011/03/02/140972.html#Feedback0http://www.shnenglu.com/tankzhouqiang/comments/commentRss/140972.htmlhttp://www.shnenglu.com/tankzhouqiang/services/trackbacks/140972.html

epoll学习(fn)W记

epoll有两U模?Edge Triggered(UET) ?Level Triggered(ULT).在采用这两种模式时要注意的是,如果采用ET模式,那么仅当状态发生变化时才会(x)通知,而采用LT模式cM于原来的 select/poll操作,只要q有没有处理的事件就?x)一直通知.

以代码来说明问题:
首先l出server的代?需要说明的是每ơaccept的连?加入可读集的时候采用的都是ET模式,而且接收~冲区是5字节?也就是每ơ只接收5字节的数?

#include  < iostream >
#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_eventl构体的变量,ev用于注册事g,数组用于回传要处理的事g
    struct epoll_event ev,events[
20 ];
    
// 生成用于处理accept的epoll专用的文件描q符
    epfd
= epoll_create( 256 );
    struct sockaddr_in clientaddr;
    struct sockaddr_in serveraddr;
    listenfd 
=  socket(AF_INET, SOCK_STREAM,  0 );
    
// 把socket讄为非d方式
    
// setnonblocking(listenfd);
    
// 讄与要处理的事件相关的文g描述W?br>     ev.data.fd = listenfd;
    
// 讄要处理的事gcd
    ev.events
= EPOLLIN|EPOLLET;
    
// ev.events = EPOLLIN;
    
// 注册epoll事g
    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事g的发?br>         nfds = epoll_wait(epfd,events, 20 , 500 );
        
// 处理所发生的所有事?nbsp;    
        
for (i = 0 ;i < nfds; ++ i)
        {
            
if (events[i].data.fd == listenfd)
            {
                clilen=sizeof(struct sockaddr);
                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;
                
// 讄用于L作的文g描述W?br>                 ev.data.fd = connfd;
                
// 讄用于注测的读操作事g
                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;
                
// 讄用于写操作的文g描述W?br>                 ev.data.fd = sockfd;
                
// 讄用于注测的写操作事g
                ev.events
= EPOLLOUT|EPOLLET;
                
// 修改sockfd上要处理的事件ؓ(f)EPOLLOUT
                
// epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd, & ev);
            }
            
else   if (events[i].events & EPOLLOUT)
            {   
                sockfd 
=  events[i].data.fd;
                write(sockfd, line, n);
                
// 讄用于L作的文g描述W?br>                 ev.data.fd = sockfd;
                
// 讄用于注测的读操作事g
                ev.events
= EPOLLIN|EPOLLET;
                
// 修改sockfd上要处理的事件ؓ(f)EPOLIN
                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,
& ev);
            }
        }
    }
    return 
0 ;
}


下面l出试所用的Perl写的client?在client中发?0字节的数?同时让client在发送完数据之后q入d@? 也就是在发送完之后q接的状态不发生改变--既不再发送数? 也不关闭q接,q样才能观察出server的状?

#! / usr / bin / perl

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 );
}

q行server和client发现,server仅仅d?字节的数?而client其实发送了(jin)10字节的数?也就是说,server仅当W一? 监听C(jin)EPOLLIN事g,׃没有d完数?而且采用的是ET模式,状态在此之后不发生变化,因此server再也接收不到EPOLLIN事g?
(友情提示:上面的这个测试客L(fng),当你关闭它的时候会(x)再次出发IO可读事glserver,此时server׃(x)去读取剩下的5字节数据?但是q一事g与前面描q的ET性质q不矛盾.)

如果我们把client改ؓ(f)q样:

#! / usr / bin / perl

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 );
}


可以发现,在server接收?字节的数据之后一直监听不到client的事?而当client休眠5U之后重新发送数?server再次监听C(jin)变化,只不q因为只是读取了(jin)5个字?仍然?0个字节的数据(clientW二ơ发送的数据)没有接收?

如果上面的实验中,对accept的socket都采用的是LT模式,那么只要q有数据留在buffer?server׃(x)l箋得到通知,读者可以自行改动代码进行实?

? 于这两个实验,可以得出q样的结?ET模式仅当状态发生变化的时候才获得通知,q里所谓的状态的变化q不包括~冲Zq有未处理的数据,也就是说,如果 要采用ET模式,需要一直read/write直到出错为止,很多人反映ؓ(f)什么采用ET模式只接收了(jin)一部分数据再也得不到通知?大多因ؓ(f)q样;而LT 模式是只要有数据没有处理׃(x)一直通知下去?

补充说明一下这里一直强调的"状态变?是什?

1)对于监听可读事g?如果是socket是监听socket,那么当有新的dq接到来为状态发生变?对一般的socket而言,协议栈中相应的缓 冲区有新的数据ؓ(f)状态发生变?但是,如果在一个时间同时接收了(jin)N个连?N>1),但是监听socket只accept?jin)一个连?那么其它? accept的连接将不会(x)在ET模式下给监听socket发出通知,此时状态不发生变化;对于一般的socket,如例子中而言,如果对应的缓冲区本n 已经有了(jin)N字节的数?而只取出?jin)小于N字节的数?那么D存的数据不?x)造成状态发生变?

2)对于监听可写事g?同理可推,不再详述.

而不论是监听可读q是可写,Ҏ(gu)关闭socketq接都将造成状态发生变?比如在例子中,如果中断client脚本,也就是主动中断了(jin)socketq接,那么都将造成server端发生状态的变化,从而server得到通知,已l在本方~冲Z的数据读?

把前面的描述可以ȝ如下:仅当Ҏ(gu)的动?发出数据,关闭q接{?造成的事件才能导致状态发生变?而本方协议栈中已l处理的事g(包括接收?jin)对方的? ?接收?jin)对方的dq接h)q不是造成状态发生变化的必要条g,状态变化一定是Ҏ(gu)造成?所以在ET模式下的,必须一直处理到出错或者完全处理完 ?才能q行下一个动?否则可能?x)发生错?


另外,从这个例子中,也可以阐qC些基本的|络~程概念.首先,q接的两端中,一端发送成功ƈ不代表着Ҏ(gu)上层应用E序接收成功, 拿上面的client试E序来说,10字节的数据已l发送成?但是上层的serverq没有调用readd数据,因此发送成功仅仅说明了(jin)数据被对 方的协议栈接收存攑֜?jin)相应的buffer?而上层的应用E序是否接收?jin)这部分数据不得而知;同样?d数据时也只代表着本方协议栈的对应 buffer中有数据可读,而此时时候在对端是否在发送数据也不得而知.



周强 2011-03-02 12:22 发表评论
]]>
ƷŮþþþþ2018| ɫɫݺɫۺϾþ| ƷþþþӰԺɫ| ŷպƷþþѹۿ| ƷþþþþĻ| wwwþþcom| ĻþþƷ1| 㽶þþþþúݺɫ| þùһ| ѹۿþþƵ| һ㽶þֻ| ձþþþƷĻ| þۺϾþۺϾɫ| Ӱһþþþó˾Ʒۺ | þ99Ʒ鶹| ɫվ޷ľþò| ۺ޾þһƷ| ŷ޾þþþƷ| þþƷ99Ʒ| ۺŮþþ30p| ۺϾþøϾþúݺݺ97ɫ | 99þþþþѿ | ?VþþƷ | þþþó˾ƷĻ | þþŷղAV | þùƷþþ| 99þùѸ| þܳ| ۺҹҹþ| þþ91Ʒһ| 鶹ھƷþþþþ| ѾƷպȾþ| ձ޷츾þþþþ| 91ƷۺϾþ㽶 | ŷɫۺϾþþþþ| ۺϾþþ| Ʒһþþþþþվ| ɫþþþۺ | Ʒþþþþ| ھƷþþþþþɬ | ˾þþùۿëƬ|