客户端定时连接服务器,但若连接不上等待时间太长了,程序动不了,像死了一样,请问如何开线程进行连接?或者用其他方法。多谢大家拉

解决方案 »

  1.   

    占用时间的主要是connect函数,你只要新开一个线程将这个函数放到线程函数中去就可以了。
      

  2.   

    class CRcvDataThread : public CWinThread
    {
    DECLARE_DYNCREATE(CRcvDataThread)
    private://variable
    CFtpCmdCtrl m_FtpCmdCtrl; //继承自MFC的SOCKET类
    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CRcvDataThread)
    public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
    virtual int Run();
    //}}AFX_VIRTUAL// Implementation
    // Generated message map functions
    //{{AFX_MSG(CRcvDataThread)
    // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG DECLARE_MESSAGE_MAP()
    };
    int CRcvDataThread::Run() 
    {
    // TODO: Add your specialized code here and/or call the base class
    if(!m_FtpCmdCtrl.Create())
    return CWinThread::Run();
    if(!m_FtpCmdCtrl.AsyncSelect())
    return CWinThread::Run();
    if(m_FtpCmdCtrl.Connect(strFtpServerName,usServerPort))
    return CWinThread::Run();
    return CWinThread::Run();
    }
      

  3.   

    我是把建立CSocket到连接服务器的代码都是放在一个承继 CWinThread 的类里面然后用 AfxBeginThread 启动线程的。
      

  4.   

    For a server socket that accepts incomming connections,
    it goes a little something like this:////////////////////////////////////////////////////
    class CMyThread: public CWinThread
    {
     // yadda yadda yadda    CMySocket m_ClientSocket; // yadda yadda yadda
    }
    ////////////////////////////////////////////////////... and ...////////////////////////////////////////////////////
    class CClientSocket: public CSocket
    {
     // yadda yadda yadda CMyThread*   m_ParentThread; // yadda yadda yadda
    }
    // Global used for passing socket to a diffr thread
    SOCKET Glob_hConnectedSocket;
    ////////////////////////////////////////////////////... and ...////////////////////////////////////////////////////
    class CServerSocket: public CSocket
    {
     // yadda yadda yadda  // Attributes
      public:
        CObList m_clients;  // Current Clients  // Overridables
      protected:
        virtual void OnAccept(int nErrorCode); // yadda yadda yadda};
    ////////////////////////////////////////////////////... then ...////////////////////////////////////////////////////
    void CServerSocket::OnAccept(int nErrorCode)
    {
      
        CSocket sConnected;
        if(Accept(sConnected))
        {  
            // Find out who we are talking to
            CString strAddr;
            UINT nPort;        if(sConnected.GetPeerName(strAddr, nPort))
                TRACE2("CONNECTED: %s, port %d\n", strAddr, nPort);        // Detach Socket; save in global variable
            Glob_hConnectedSocket = sConnected.Detach();        // Launch new thread to handle this connection
            // also, create initially suspended
            CSockThread* pClientThread = (CMyThread*)
                AfxBeginThread(
                    RUNTIME_CLASS(CMyThread), 
                    THREAD_PRIORITY_NORMAL, 0, 
                    CREATE_SUSPENDED, NULL );        // Add Client to server socket's client list
            // You'll need to delete the CMyThread objects
            m_clients.AddTail(pClientThread);        // Set client thread's m_bAutoDelete to FALSE; 
            // we will clean up with CWinThread object ourselves
            pClientThread->m_bAutoDelete = FALSE;        // Resume the thread for execution
            pClientThread->ResumeThread();
       
        }
        else
        {
            // This would be unusual
            TRACE("CServerSocket::OnAccept()- Accept Failed!\n");
            return;
        }
    }
    ////////////////////////////////////////////////////... and ...////////////////////////////////////////////////////
    BOOL CMyThread::InitInstance()
    {
        // Attach socket object to socket handle
        if(m_ClientSocket.Attach(Glob_hConnectedSocket) == FALSE)
            return FALSE;
     
        // Set Parent Thread property of socket
        m_ClientSocket.m_ParentThread = this;    // Successful
        return TRUE;
    }
    ////////////////////////////////////////////////////Basically, you must detach the socket and attach back to it
    in the context of the thread you want to control it.In the case above, the listening socket that accepts connections is
    serialized -- so the Glob_hConnectedSocket handle won't ever be used
    by more than one thread at a time.
      

  5.   

    请问各位,你们把CSocket对象放到线程以后,如果要调用该SOcket对象发送数据该如何做?
    谢谢!有谁有更具体的代码?马上揭帖。
      

  6.   

    你的意思是多个线程共享一个SOCKET发送数据吗?
      

  7.   

    多个线程共享一个SOCKET时,需要谨慎
      

  8.   

    多个线程共享一个SOCKET时,需要谨慎===============
    如果是一个线程读另一个线程发送,则没有任何问题,因为SOCKET本来就支持迸发进行的。
      

  9.   

    我怎么没看出,有使用多个线程共享一个SOCKET的意思.
    :(
      

  10.   

    偶的意思是,你再线程中用这个Socket连接到服务器,那么要给服务器发送数据时不是要用到这个Socket么? 但你这个Socket对象是作为线程类中的一个成员创建中的,现在我要在主线程中发送数据,应该如何调用呢?
      

  11.   

    KINGZAI的代码是服务器端的程序.为每个连接到服务器的客户开辟一个新的线程来处理服务
      

  12.   

    回复人: heartthrob(移动的心) ( ) 信誉:98  2003-09-17 18:07:00  得分:0 
     
     
      偶的意思是,你再线程中用这个Socket连接到服务器,那么要给服务器发送数据时不是要用到这个Socket么? 但你这个Socket对象是作为线程类中的一个成员创建中的,现在我要在主线程中发送数据,应该如何调用呢?
      
    ==================
    简单,开辟一个缓冲区,主线程放数据,发送线程取数据。
    不过,我不明白,为什么你的Socket对象要在线程中临时创建呢?你可声明在主线程,在子线程中去create bind send等等。这样,你在子线程中也可以调用父类的发送函数。
      

  13.   

    我开始的时候尝试对象在主线程中创建,然后将该Socket对象指针传递到线程中去连接服务器,但总出现莫名其妙的错误。不知道是不是因为我传递的有问题。
      

  14.   

    to  fsxdxh(假行僧) :
    我的程序是分模块的,Socket由我创建,但其他人写的模块可以调用,因此发送数据的时候一定是在主线程中的。我这里要解决的就是连接的时候不能像死机一样。
      

  15.   

    CSocket类先生不足,在线程中用有很大的问题,首要问题是,在线程中,无法接收到窗口消息,所以,你得在线程中定时执行以下语句:
    MSG msg;
    Sleep( 5 );
    if ( ::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE ) )
    {
    ::TranslateMessage( &msg );
    ::DispatchMessage( &msg );
    }其次,因为线程中操作还会出现关闭套接字等问题,最好在每个用到CSocket对象的线程中要运行一次以下代码:
    #ifndef _AFXDLL
    #define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
    #define _afxSockThreadState AfxGetModuleThreadState()
    // setup maps and lists specific to socket state
    _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
    if (pState->m_pmapSocketHandle == NULL)
    pState->m_pmapSocketHandle = new CMapPtrToPtr;
    if (pState->m_pmapDeadSockets == NULL)
    pState->m_pmapDeadSockets = new CMapPtrToPtr;
    if (pState->m_plistSocketNotifications == NULL)
    pState->m_plistSocketNotifications = new CPtrList;
    #endif如果套接字不是在线程中创建,而是在线程中调用另外的类中的对象来创建的话,删除时,可能会用到Attach函数.以下为在线程中连接服务器并保持连接的线程函数,仅供参考(套接字对象在另外的类中创建)
    UINT ConnectThread(LPVOID lpParam)
    {
    CVFMDlg *pDlg = (CVFMDlg*)lpParam; #ifndef _AFXDLL
    #define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
    #define _afxSockThreadState AfxGetModuleThreadState()
    // setup maps and lists specific to socket state
    _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
    if (pState->m_pmapSocketHandle == NULL)
    pState->m_pmapSocketHandle = new CMapPtrToPtr;
    if (pState->m_pmapDeadSockets == NULL)
    pState->m_pmapDeadSockets = new CMapPtrToPtr;
    if (pState->m_plistSocketNotifications == NULL)
    pState->m_plistSocketNotifications = new CPtrList;
    #endif pDlg->ConnectVFMServ(); time_t tVFMCurrent;
    CClientSocket *pSocket = NULL; HANDLE hEvent = pDlg->m_hEvtStop;
    DWORD dwWaitResult;
    while (TRUE)
    {
    MSG msg;
    Sleep( 5 );
    if ( ::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE ) )
    {
    ::TranslateMessage( &msg );
    ::DispatchMessage( &msg );
    }
    dwWaitResult = WaitForSingleObject(hEvent, 5);
    if ( dwWaitResult == WAIT_OBJECT_0 )
    {
    break;
    }
    time(&tVFMCurrent);
    pSocket = pDlg->m_pVFMSocket;
    // ¼ì²éÁ¬½Ó״̬
    if ( !pDlg->m_bConnectVFMSucc )
    {
    if ( (tVFMCurrent - pDlg->m_tLastConnVFMServerTime) > pDlg->m_config.nRepeatTime )
    {
    pDlg->ConnectVFMServ();
    }
    continue;
    }
    }
    return 0;
    }如果不想有上述的麻烦,建议自己写一个类,就不用担心线程中收不到信息(用事件而且用消息)
      

  16.   

    最后有个错别字,是用事件,而不用消息!
    用select()函数!
      

  17.   

    to  heartthrob(移动的心):
    我的程序是分模块的,Socket由我创建,但其他人写的模块可以调用,因此发送数据的时候一定是在主线程中的。我这里要解决的就是连接的时候不能像死机一样。
    --------------------------------------------
    其实,如果在主线程中进行,不但是连接象死机,发送、接收都有可能象死机的。因为是阻塞调用,除非你用AsySocket类。在主线程中发数据,与在子线程中发数据没有什么区别,而且更容易处理界面上的事。
    不过,你上面说的我不是十分明白。如果真要在主线程中发数据,你只是想解决连接时别象死机,你完全可以在一个线程中去创建、连接,连接成功后再通知主线程(比如采用CEvent类等)可以发送数据了。(这样的思路想起来真有点怪呢)
      

  18.   

    谁能给我发采用MFC CSocket的多线程客户端的例子?单独开200分送上。谢谢。
      

  19.   


    www.codeproject.com
    www.codeguru.com
    CC