CAsyncSocket in einem Thread



  • Ich möchte eine Socketverbindung in einem Client aufbauen. Stelle ich die Verbindung im normalen Hauptthread in dem meine Dialog läuft, funktioniert es einwandfrei. (Habe da einen Button wenn der angeklickt wird wird die Verbindung aufgebaut).

    Jetzt will ich aber in einem eigenen Thread diese Verbindung aufbauen, da ich z.b. erst bei bestimmten ereignissen oder nach einer gewissen Zeit dies machen will. In dem fall kann ich ganz normal die Verbindung aufbauen, es werden dann aber keine Funktionen der von CAsyncSocket abgeleiteten Klasse aufgerufen (OnConnect, OnReceive) so das ich keine Daten empfangen kann. Ich glaube das da irgendwas mit der initalisierung nicht stimmt.

    Hier paar Codeausschnitte:

    //Hier der Verbindungsaufbau
    Server = new CMySocket(this);
    if(!Server->Create())
        m_pWnd->Log.write(LOG_ERROR,"Server-Socket konnte nicht aufgebaut werden");
    if(!Server->Connect(m_pWnd->gData.getSIP(),m_pWnd->gData.getSPort()) && (error = Server->GetLastError()) !=10035){    
        char msg[255];
        sprintf(msg,"Fehler beim Server-Verbindungsaufbau: %i",error);        
        m_pWnd->Log.write(LOG_ERROR,msg); //Schreibt fehler in eine LogDatei
    }
    
    //CMySocket ist von CAsyncSocket abgeleitet und dort habe ich die Methoden OnConnect usw. überladen.
    protected:
    virtual void OnSend(int nErrorCode);
    virtual void OnReceive(int nErrorCode);
    virtual void OnClose(int nErrorCode);    
    virtual void OnConnect(int nErrorCode);    
    virtual void OnAccept(int nErrorCode);
    
    //Und hier z.b die OnConnect
    void CMySocket::OnConnect(int nErrorCode){    
    // Sind Fehler aufgetreten?   
    if (nErrorCode == 0)        
    // Nein, OnConnect-Funktion des Dialogfelds aufrufen
            m_pWnd->OnConnect(this);
    else m_pWnd->OnError(nErrorCode);
    }
    


  • versuchs mal so:

    CSocket Socket;            // die von ASyncSocket abgeleitete klasse
    Socket.SetParent(this);
    
    m_Socket.Create();
    m_Socket.Connect(cVerb_SvrAdress, iVerb_Port);
    

    du übergibst die funktionen OnConnect u.s.w an deine hauptdialogfeldklasse. vermute du hast das beispiel aus dem buch genommen. wenn ich mich nicht irre sind die funktionen die deine socketklasse aufruft (im hauptdialog) nicht public, oder !? mach die auch noch public.

    bei mir klappts ja schließlich auch 😉



  • Ich habe den Konstruktor überladen so das ich die SetParent-Methode nicht aufrufen muss, weil ich dem Konstruktor schon den Parent mitgebe. Ausserdem sind die überladenen Klassen doch auch protected also ist es doch in Ordnung wenn ich die OnConnect usw. in der MySocket auch protected mache, oder?

    Er geht gar nicht in die OnConnect von MySocket rein, also kann es nicht an der OnConnect von der Vaterklasse liegen.

    Ich habe ja den starken Verdacht das wenn ich in einem Thread die Connect-Funktion von der CAsyncSocket aufrufe, der nicht richtig initalisiert wird und deshalb auch nicht die OnConnect aufgerufen werden. Aber wie mache ich das, das es richtig initalisiert wird?



  • igE schrieb:

    Ich habe den Konstruktor überladen

    stimmt, hab nicht richtig hingeguckt, sry.

    ich könnte mir vorstellen das es am thread liegt. ich hab auch schon einiges versucht im thread zu machen, aber das klappt e nicht wirklich. aber in der hauptdialogfeldklasse ging es.

    das letzte was ich versuchen würde ist von der threadklasse aus auf die dialogfeldklasse gehen und da ne funktion aufrufen in der du deinen socket initialisierst, verstehste !?



  • Habe gerade leider den Code nicht (am Montag wieder)
    Aber ich rufe aus der Threadfunktion eine Methode einer Klasse auf die für die Kommunikation zuständig ist. Diese Funktion hat eine Endlosschleife. In der Öffne ich auftreten von einem Ereignis die Socketverbindung. Aber das geht leider nicht. Aber warum bloss.
    Kann am Montag den Threadcode mal hier reinstellen.



  • ich meine das so (ich mache das auch so vom prinzip her bei anderen problemen):

    du rufst von deiner hauptdialogfelsklasse deinen thread auf:

    CThreadClass* m_xDisplayThread;
    
    m_xDisplayThread = (CThreadClass*)
    AfxBeginThread(RUNTIME_CLASS(CThreadClass), NULL, 0, CREATE_SUSPENDED); 
    
    m_xDisplayThread->SetOwner(this); 
    m_xDisplayThread->ResumeThread();
    

    aus der int CThreadKlasse::Run() -funktion kannst dann folgendes machen:

    m_pOwner->DeineFunktion();     // hier kannst du dann den socket initialisieren
    

    ich meine damit das du alles von deiner dialogfeldklasse aus steuerst.
    kann mir nur vorstellen das daran liegen könnte. du kannst ja von einem thread ja auch nicht direkt auf einen anderen thread zugreifen, nur vom thread aus auf deine dialogfeldklasse.



  • Ich habe in meiner Klasse den Thread so deklariert

    CWinThread* m_ConnectThread;
    

    Dann starte ich den Thread so

    m_ConnectThread = AfxBeginThread(MyTransCtrlFunction ,(LPVOID)this);
    

    Und in dort rufe ich dann eine Funktion auf die eine endlos-schleife hat und bei events die Verbindung aufbauen oder schliessen soll.

    UINT MyTransCtrlFunction(LPVOID pParam)
    {
    	((CDataTransCtrl*) pParam)->ConnectThread();
    	return 0;
    }
    
    void CDataTransCtrl::ConnectThread()
    {
        while(1)
       {
    	// Wartet bis die Verbindung aufgebaut werden muss
    	::WaitForSingleObject(m_pWnd->g_eventSConnect,INFINITE);
    	// löscht die vielleicht noch anliegenden Close-Events
    	::WaitForSingleObject(m_pWnd->g_eventSClose,0);
    
                 .....
                // Hier wird die Verbindung aufgebaut (s.ersten Eintrag)		
    
    	// Wartet bis die Verbindung geschlossen werden muss
    	::WaitForSingleObject(m_pWnd->g_eventSClose,INFINITE);
    	// löscht die vielleicht noch anliegenden Connect-Events
    	::WaitForSingleObject(m_pWnd->g_eventSConnect,0);
    
    	  .........
                 //Hier wird die Verbindung wieder geschlossen
       }
    }
    

    So funktioniert das aber nicht. Welche Thread nimmst du den wo man eine Run-Methode hat? Vielleicht geht das ja mit der.



  • bei mir sieht das so aus:

    - Erst erstellst du ne Klasse die abgeleitet von 'CWinThread' ist.
    dann fügst du diese funktionen / variablen in deine threadklasse ein (public):

    void SetOwner(CHauptDlg* pOwner);
    	CHauptDlg* m_pOwner;                  // hauptdialogfeld-klasse var.
    	CHauptDlg* m_dialogvar;               // hauptdialogfeld-klasse var.
    	virtual int Run();
    

    in die funktion 'SetOwner(CHauptDlg* pOwner)' setzt du das:

    m_pOwner = pOwner;
    

    in die funktion 'int Run()' setzt du dann das was deine Threadklasse machen soll (von da kannst du auch über deine m_pOwner -variable aus über dein hauptdialogfeld alles machen was du willst.

    - In die threadklasse kommt natürlich noch die headerfile vom hauptdlg.
    - im hauptdlg erstellst du dann eine variable (auch public):

    CThreadClass* m_xDisplayThread;       // thread-klasse var.
    

    - und in die headerfile deiner hauptdialogfeld-klasse mußt du dann auch noch die threadklasse angeben:

    class CThreadClass;
    

    wenn du jetzt noch die headerfile deiner threadklasse in dein hauptdialogfeld einfügst kannst du damit arbeiten.
    den thread ruftst du jetzt so auf:

    m_xDisplayThread = (CThreadClass*)
    	AfxBeginThread(RUNTIME_CLASS(CThreadClass), NULL, 0, CREATE_SUSPENDED); 
    
    	m_xDisplayThread->SetOwner(this); 
    	m_xDisplayThread->ResumeThread();
    

    wenn das dann immer noch nicht klappt, was ich glaube 🙄, dann initialisier den socket mal in deiner hauptdialogfeldklasse und versuch das dann mal so ...



  • Wenn ich diese Zeile schreibe:

    m_ConnectThread = (CConnectThread*) AfxBeginThread( RUNTIME_CLASS ( CConnectThread ), NULL, 0, CREATE_SUSPENDED);
    

    Bekomme ich egal ob die leerzeichen bei RUNTIME_CLASS(CConnectThread) reinmache oder weglasse folgenden Compilerfehler:

    error C2039: 'classCConnectThread' : Ist kein Element von 'CConnectThread'

    Was bedeutet das? Und wie kriege ich den weg?



  • kann jetzt echt nicht sagen was du da falsch / anders gemacht hast. haste ICQ oder sowas !? dann kann ich dir mal nen beispiel schicken



  • Ja, meine ICQ-Nummer ist 112191425. Wäre nett wenn du mir mal was schicken könntest.


Anmelden zum Antworten