本帖最后由 oyljerry 于 2013-07-08 16:46:28 编辑

解决方案 »

  1.   

    采用异步的就可以吧,开30个线程要占多少资源啊。WSAAsyncSelect可以处理过来,这有socket例子,Finger用了WSAAsyncSelect,你看看:
    http://download.csdn.net/detail/geoff08zhang/4571358
      

  2.   


    我觉得是不是因为这样,假设是服务器的话,在FD_ACCEPT有响应的时候,我们创建一个放SOCKET的容器,把每个客户端的socket放进去,这样子我们不用开线程,只要根据不同的socket服务器也可以和不同的客户端交流
     
    但是作为客户端,客户端只能连接一个服务器所以FD_CONNECT只能做一次响应,如果要连接多个服务器的话这样子是不是不行啊?我尝试用一个函数去搜索服务器,假设搜索192.168.1.20-192.168.1.30这个网段```我的服务器IP是192.168.1.15,当搜索到192.168.1.15的时候并没有跳转到WSAAsyncSelect设定的消息响应函数里.除非我的服务器是192.168.1.20他才最后在搜索完所有的IP以后才跳进去``感觉就好像它只默认最后一次连接的消息响应`这是为什么呢?
      

  3.   

    有点晕。class My : public CAsyncSocket;vector<My*> vec;每扫描到一个服务器,就My* m = new My; m->Create();  m->Connect();  然后在OnConnect中把自己加入到vec中。
      

  4.   

    我也喜欢周杰伦``````好吧```我还有几个问题想问一下````
        1.扫描服务器的时候不是就已经要create然后connect了么?如何在扫描完之后再create呢?
        2.CAsyncSocket应该有一个消息响应函数响应FD_CONNCET FD_READ FD_CLOSE等事件,我在程序中create了多个socket,那么这个消息响应函数是响应的哪一个socket的事件呢?
        3.本人菜鸟vector没怎么用过,这个我会再看看,有问题再来请教```
      

  5.   

    扫描完再create?那你先把扫描到的 服务器ip和port保存下来,扫描完成后再去connectCAsyncSocket的使用方法
    class My : public CAsyncSocket
    {
    public:
    virtual void OnConnect(int e){ if(e == 0) 连接成功; else 连接失败,错误码为e; }
    };
      

  6.   

    扫描完再create?那你先把扫描到的 服务器ip和port保存下来,扫描完成后再去connectCAsyncSocket的使用方法
    class My : public CAsyncSocket
    {
    public:
    virtual void OnConnect(int e){ if(e == 0) 连接成功; else 连接失败,错误码为e; }
    };    不知道我理解错了没啊,对于客户端而言扫描服务器不就是按照设定好的网段挨个尝试去连接服务器么?那么这个实现过程就是先socket.create(),然后socket.connect(IP,PORT),然后IP或者端口改变再尝试去连接.这样子在连接成功之前肯定要先create,connect啊.那为什么要在扫描到服务器以后再create,connect呢?     你的意思是不用去管那个消息响应函数么?直接通过connect的返回值确定服务器是否开启?那如果我有地反需要用到服务器关闭就是FD_CLOSE这个事情的时候又应该怎么办呢?
      

  7.   

    你的意思是 每扫描到服务器后,就Create,通过Connect来判断是否可用?没这个必要。
    class My : public CAsyncSocket
    {
    public:
    virtual void OnConnect(int e){ if(e == 0) 连接成功; else 连接失败,错误码为e; }
    };
    对于每个服务器,new一个My,调用Connect,在OnConnect中,如果成功,就把自己加入vector<My*>中,如果失败,就delete this。
    服务器关闭的时候,会收到FD_CLOSE,在OnClose中从vector移除自己后delete this
      

  8.   


    不是,我的意思是create和connect应该在扫描之前.我大概懂你的意思了````但是服务器关闭那里```消息响应函数只有一个```我怎么知道是那个socket响应了FD_CLOSE这个事件呢````
      

  9.   

    class My : public CAsyncSocket
    {
    public:
    virtual void OnConnect(int e){ if(e==0) 连接成功;else 连接错误; }
    virtual void OnClose(int e){ if(e==0) 关闭连接;else 连接断开 }
    };每一个My都有这样的消息响应。
      

  10.   

    这里的OnConnect和OnClose函数都是void类型``````假设我my socket;然后socket.connect的时候是没有数据返回的,你所谓的消息响应我怎么去知道呢?
      

  11.   

    My此处是异步的,
    My* m = new My;
    m->Create();
    m->Connect();当有FD_CONNECT事件发生时,由系统自动去调用OnConnect函数
      

  12.   


    嗯`````这个我知道````可是据我所知异步都是会在WSASyncSelect()这个函数中定义一个消息响应函数,然后再消息响应函数中去实现对FD_ACCPT FD_RECIVE FD_CONNECT等消息的响应.但是你知道一个程序中,至少一个MFC类中只能有一个消息响应的函数,我开始的时候有试过用异步编,但是实际在操作的时候貌似不是每次connect以后FD_CONNECT都会有响应,而是好像是最后一次connect执行完了以后,FD_CONNECT才有响应,这个是哪里有出什么问题么?
      

  13.   

    CAsyncSocket已经封装了WSAAsyncSelect函数,这个不用你自己取做了。我们只需要关心OnConnect,OnClose这些函数就行了
      

  14.   


    不好意思啊`````因为之前一直用的winsock编的```对于CSOCKET和CASYNCSOCKET这些封装类都不够了解````今天认真认真看了一下`````你的意思应该是在CASYNCSOCKET中重载OnConnect这个消息响应函数,这个就相当于是FD_CONNECT响应了.那实现多服务器扫描过程这样子行不?
    My* m = new My;
    m->Create();
    m->Connect();然后在OnConnect{if(e==0) 加入vector<My*>;else 主对话框指针->delete m;}我这样直接在消息响应中添加m到vector或者删除m是可行的么?我还想请教下```如果我要接收数据我只需要重载OnRecive应该就可以了吧````但是如果数据我要存储起来我应该怎么进行存储呢?是在主对话框中建立缓存区域,还是在CAYNCSOCKET中建立呢?发送数据的话我又怎么去发送到对应的服务器呢?
    本人菜鸟````谢谢了`````
      

  15.   

    我这样直接在消息响应中添加m到vector或者删除m是可行的么?  可行如果数据我要存储起来我应该怎么进行存储呢?  
    给My添加一个成员变量 string in_buf;  然后在OnReceive中
    int n = 0;
                            char buf[32*1000];
    while(true)
    {
    n = Receive(buf, 32*1000);
    if(n <= 0)
    break;
    else // 正常接收数据
    in_buf.append(buf, n);
    }
    ok,此次数据接收完毕,可以去处理数据了发送数据的话我又怎么去发送到对应的服务器呢?  直接调用 My->Send()就行了
      

  16.   


    谢谢你的耐心解答啊```````我稍微多问几点啊......关于存储也就是说我直接把缓存空间添加到MY这个类里````这样子我每次new MY的时候就创建一个独立的存储空间,和不同的服务器连接上以后是将数据分开存储的,我需要使用这些数据的时候MY->buf就能读取到这些数据了,是这个意思吧?发送的时候我应该先从VECTOR里将MY取出再调用My->Send()就可以和对应的服务器进行通信这样?大概原理我是懂了,可是有些细节我还是有点问题
    比如说:
    for(IP地址++) {  MY* m=new MY; m->create();m->connect(port,IP)} 假设我是在for循环中创建的m;这样子我如何能在消息响应中去删除掉这个m呢? 
      

  17.   

    我需要使用这些数据的时候MY->buf就能读取到这些数据了,是这个意思吧?  是的发送的时候我应该先从VECTOR里将MY取出再调用My->Send()就可以和对应的服务器进行通信这样? 是的这样子我如何能在消息响应中去删除掉这个m呢?   在OnConnect中,if(e) delete this;  e=0表明连接成功,否则连接失败其中e代表错误码
      

  18.   


        用delete this就可以实现了?太感谢了````真的学了不少知识`````   开始我是在线程中MY *m=new MY;发现OnConnect()一直没有响应.后来放到主进程中就没有问题了`````看来我对异步非阻塞的理解还非常不够啊`````    不知道能给个QQ不`````,有问题的时候我再请教你````真的谢谢了````
      

  19.   

    Connect不能放在线程中,因为线程中没有消息循环,而CAsyncSocket利用的是窗口消息循环来通知用户的。
      

  20.   


    哦``受教了```也就说异步的话就不能用线程了?如果我这边客户端要超找的网段的IP可能在100个左右,然后最后连接上服务器的可能在20个左右```是用异步比较好,还是用CSOCKET+线程比较好呢?我OnConnect函数现在是这样的
    if (nErrorCode==0)
    {
        m_dlg->SetDlgItemText(IDC_EDIT1,"C");
    }
    else
    {
    delete this;
    }
    CAsyncSocket::OnConnect(nErrorCode);
    但是我跟踪代码的时候发现只有if (nErrorCode==0)即连接成功的时候才运行到了这个函数里````else即失败的时候没有反应.