1.为什么在一开始创建了一个线程,然后立即就关闭它了?
2.在关联好完成端口和套接字之后,为什么还要发出对客户端的I/O请求,等待完成消息?
3.在工作线程中,在处理过客户端消息后为什么也要发出对客户端的I/O请求?
4.那个自定义的PerHandleData,自己什么都能往里面定义而不会出错吗?盯着书看,没看懂,在网上找了好多文章,也都无济于事,看了三天了,希望哪位大侠能救命

解决方案 »

  1.   

    1.为什么在一开始创建了一个线程,然后立即就关闭它了? 
    >>没有听说过有如此需要或者示例做法2.在关联好完成端口和套接字之后,为什么还要发出对客户端的I/O请求,等待完成消息? 
    >>关联关联,并不表示操作。仅仅只是表示相应的工作由谁来完成。但是具体做什么还需要用户指定3.在工作线程中,在处理过客户端消息后为什么也要发出对客户端的I/O请求? 
    >>所谓完成端口,重点在于“完成通知”,当一件事情做完之后,通知了用户线程,则它(们)的任务就已经到此结束,而如果需要他们再继续做什么事情,仍然需要另外安排4.那个自定义的PerHandleData,自己什么都能往里面定义而不会出错吗? 
    >>不清楚具体指哪一个函数的哪一个参数,建议在使用此类名称时,要么直接指出某某函数/过程的第N个参数,或者参考MSDN取名,否则没有一个标准的话,除也你自己,谁也不知道PerHandleData是什么。
      

  2.   

    和楼上一样~
    PerHandleData还不知道是啥东东~
    LZ从什么地方看到的???
      

  3.   

    相对扩充来讲,GetQueuedCompletedStatus当中的四个参数,第一个是返回的完成数据大小,是一个数值,不可以扩充,第二个是相对套接字(Socket)的一个关联或者描述,是一个用户标识,可以任何扩充,但是基本上只是当是当前SOCKET的全局参数信息载体比较多,第三个参数是一个Overlapped,具有一个Overlapped对齐结构需要供系统进行操作,包括事件(Event)通知等。但是由于系统改变的只是结构体当中相应位置的数据,并不会改变地址,所以我们就完全可以传一个基址给系统操作并且分配的长度足够,而使得系统操作的时候不越界就可以了,多余的部分具体多少,系统并不会关心,而我们自己却可以利用之。之所以任意扩充(其实这里面所谓的任意扩充是错误的,仅仅只是固定结构后面可以任何的扩充),我们可以看如下一个示例(关于操作内存对齐,其实早前我曾经在一些贴子当中提到过):1.声明一个结构体A(包含2个int成员)typedef struct _tagA{
       int a0;
       int a1;
    }_A,A,*LPA;
    2.声明一个结构体B(B中有一个A结构,加外2个int成员,总结构应该是4个int成员)typedef struct _tagB{
       A a;//前面采用了typedef声明,所以这里的A不需要带struct关键字
       int b0;
       int b1;
    }_B,B,*LPB;
    3.声明一个结构体C(包括了4个int成员)typedef struct _tagC{
       int a0;
       int a1
       int b0;
       int b1;
    }_C,C,*LPC;
    然后我们来使用这些结构体:LPC c;//一个C结构指针,同时我们也可以简单地看做是,一个包括4个int成员数据类型的指针
    LPB b;//一个B结构指针,同时我们也可以简单地看做是,一个包括4个int成员数据类型的指针
    LPA a;//一个A结构指针,同时我们也可以简单地看做是,一个包括2个int成员数据类型的指针b=new B;//输入出b的数据(正常的程序这里应该需要先对b进行初始化),但是测试程序就当是给它赋了随机值
    cout <<'b->a.a0='<<b->a.a0<<endl;
    cout <<'b->a.a1='<<b->a.a1<<endl;
    cout <<'b->b0='<<b->b0<<endl;
    cout <<'b->b1='<<b->b1<<endl;//对b,按A结构进行赋值
    a=(LPA)b;
    a->a0=190;//随便赋值
    a->a1=345;//再次输入b的数据
    cout <<'b->a.a0='<<b->a.a0<<endl;
    cout <<'b->a.a1='<<b->a.a1<<endl;
    cout <<'b->b0='<<b->b0<<endl;
    cout <<'b->b1='<<b->b1<<endl;//接下来再对b按C结构去赋值
    c=(LPC)b;
    c->a0 = 900;
    c->a1 = 876l
    c->b0 = 456;
    c->b1 = 97;//又一次输入b的数据
    cout <<'b->a.a0='<<b->a.a0<<endl;
    cout <<'b->a.a1='<<b->a.a1<<endl;
    cout <<'b->b0='<<b->b0<<endl;
    cout <<'b->b1='<<b->b1<<endl;delete c;由上面的程序得到的结果说明了,虽然声明的类型是B,但是我们对它分别按照A和C结构去操作,同样可以完成类似对B结构操作一样的效果。这就是内存操作当中的相对位置对齐。同样的,由上面的示例可以得出,我们可以声明任意一个在最前面包括有两个int元素的结构体按A进行操作,当前建议这个结构体是按B那样去包括A结构,而不是C那样仅仅只是伪造一个结构,因为象B那样去声明,当我们改变了A的结构之后,只要重新编译就能得到理想中的结果,但是C却可能会引起相当的麻烦事情。
      

  4.   

    1.为什么在一开始创建了一个线程,然后立即就关闭它了?   
    你是说立即CloseHandle吧,那只是在主线程中减少对线程handle的引用,但线程本身并没有关闭。3.在工作线程中,在处理过客户端消息后为什么也要发出对客户端的I/O请求?   
    主线程只是起了个开头的作用,工作线程处理完一件事又给自己安排了下一件事,我是这样理解的。