CAsyncSocket: Als Client verbinden sobald der Host vorhanden ist.



  • *push*


  • Mod

    Viele MFC Objekte sind threadafin. D.h. Du kannst Sie nur in dem Thread benutzen, der sie erzeugt.

    Du erzeugst global (im ertsen Thread) CMySocket Objekte. Diese gehören also diesem "Main-Thread". Dann bentzt Du diese aber in einem anderen Thread.

    Das muss knallen.

    Erzeuge Deine CMySocket Objekte in dem Workerthread!



  • Ich habe es so mal versucht, bekomme aber noch die selbe Meldung:

    CMySocket *CSocket02Dlg::m_psListenSocket;
    CMySocket *CSocket02Dlg::m_psConnectSocket;
    
    unsigned int CSocket02Dlg::TrySocketConnect(LPVOID pParam)
    {
    	m_psConnectSocket = new CMySocket;
    	m_psListenSocket = new CMySocket;
    
    	m_psConnectSocket->SetParent((CDialog *)pParam);
    	m_psListenSocket->SetParent((CDialog *)pParam);
    
    	//--- Versuchen als Client Verbindung 
    	//--- zu einem Server zu bekommen
    	if(!m_psListenSocket->Create())
    		RETAILMSG(1,(_T("m_psListenSocket->Create: %d\n\r"), GetLastError()));
    
    	while(!m_psListenSocket->Connect(_T("172.31.255.1"), 6000))
    	{
    		RETAILMSG(1,(_T("Try to Connect\n\r")));
    		Sleep(1000);
    	}
    
    	RETAILMSG(1,(_T("Connected now!\n\r")));
    
    	return 0;
    }
    
    BOOL CSocket02Dlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	AfxBeginThread(TrySocketConnect, (LPVOID)this);
    ...
    ...
    
    private:
    	static unsigned int TrySocketConnect(LPVOID pParam);
    	static CMySocket *m_psListenSocket;
    	static CMySocket *m_psConnectSocket;
    

    Ich habe es auch mal mit lokalen Objekten im Thread probiert, aber auch die selbe Meldung:

    unsigned int CSocket02Dlg::TrySocketConnect(LPVOID pParam)
    {
    	CMySocket *lsListenSocket;
    	CMySocket *lsConnectSocket;
    
    	lsConnectSocket = new CMySocket;
    	lsListenSocket = new CMySocket;
    
    	lsConnectSocket->SetParent((CDialog *)pParam);
    	lsListenSocket->SetParent((CDialog *)pParam);
    
    	//--- Versuchen als Client Verbindung 
    	//--- zu einem Server zu bekommen
    	if(!lsListenSocket->Create())
    		RETAILMSG(1,(_T("m_psListenSocket->Create: %d\n\r"), GetLastError()));
    
    	while(!lsListenSocket->Connect(_T("172.31.255.1"), 6000))
    	{
    		RETAILMSG(1,(_T("Try to Connect\n\r")));
    		Sleep(1000);
    	}
    
    	RETAILMSG(1,(_T("Connected now!\n\r")));
    
    	return 0;
    }
    

    Was habe ich falsch gemacht?



  • *push*



  • Was macht SetParent? Warum bekommen die Socket Objekte einen Zeiger auf einen CDialog?
    Sieht so aus, als würden die Socket Klassen irgendetwas mit dem Dialog machen. Das geht wohl schief.



  • Das war in einem Tutorial so beschrieben. In den Ereignishandlern der Socketklasse wird einfach nur eine Methode der Dialogfunktion aufgerufen...

    Wie dem auch sei, ich habe das geändert. Sprich, die SetParent Methode wird im Thread nicht mehr aufgerufen, aber der Fehler bleibt.

    Um den Fehler nochmal genauer zu beschreiben: Der Fehler tritt bei dem Aufruf von lsListenSocket.Create() auf. In dem Ausgabefenster von VS steht dann die Zeile 'ASSERT_VALID fails with NULL pointer.'

    Auf dem WinCE Desktop erscheint die Fenster mit folgendem Inhalt:

    Debug Assertion Failed!

    Program: \Program
    Files\....Socket02.exe

    File:
    f:\dd\vctools\vc7libsce\ship\atl
    mfc\include\afxtempl.h
    Line: 1707

    (Press Retry to debug the
    application)

    Abort Retry Ignore

    Wenn ich Retry drücke wird die Datei objcore.cpp geöffnet und es wird an folgender Stelle angehalten:

    /////////////////////////////////////////////////////////////////////////////
    // Diagnostic Support
    
    #ifdef _DEBUG
    void AFXAPI AfxAssertValidObject(const CObject* pOb,
    	LPCSTR lpszFileName, int nLine)
    {
    	if (pOb == NULL)
    	{
    		TRACE(traceAppMsg, 0, _T("ASSERT_VALID fails with NULL pointer.\n"));
    		if (AfxAssertFailedLine(lpszFileName, nLine))
    			AfxDebugBreak();                        //<--- hier wird abgehalten
    		return;     // quick escape
    	}
    

    Wenn ich dann weiterlaufen lasse kommt:

    Unhandled exception at 0x0001ca34 in Socket02.exe: 0xC0000005: Access violation.

    Kann da jemand was mit anfangen?



  • *push*



  • Hat keiner eine Idee?



  • Dein CObject-Zeiger is an der Stelle NULL, also das existiert noch nicht oder nicht mehr oder wie auch immer.



  • Aber unmittelbar davor erstelle ich das Objekt doch....

    Und der selbe Code funktioniert ja auch wenn ich ihn im Main Thread ausführe. Das Problem tritt nur auf wenn ich dies in einem weiterm Thread mache 😞



  • So wie Martin Richter schon geschrieben hat, ich zitiere:

    Viele MFC Objekte sind threadafin. D.h. Du kannst Sie nur in dem Thread benutzen, der sie erzeugt.

    Du erzeugst global (im ertsen Thread) CMySocket Objekte. Diese gehören also diesem "Main-Thread". Dann bentzt Du diese aber in einem anderen Thread.

    Das muss knallen.

    Erzeuge Deine CMySocket Objekte in dem Workerthread!

    Versuch mal deine CMySocket Objete nicht im Thread anzulegen, sondern beispielsweise in OnInitDialog, bevor du den Thread startest.



  • Source2702 schrieb:

    Versuch mal deine CMySocket Objete nicht im Thread anzulegen, sondern beispielsweise in OnInitDialog, bevor du den Thread startest.

    Die Objekte existieren doch schon, da sie Membervariablen des Dialogs sind, wenn ich das richtig verstanden hab. Du meinst sicher das das Create außerhalb des Threads passieren sollte... Das würde ich auch als nächstes testen. Damit läuft nur noch das while() im Thread.



  • Du erzeugst sie mit new im Thread, wie ich gesehen habe.
    Erzeuge sie (mit oder ohne new) im Hauptthread. Sollte das Problem lösen.



  • Source2702 schrieb:

    Du erzeugst sie mit new im Thread, wie ich gesehen habe.
    Erzeuge sie (mit oder ohne new) im Hauptthread. Sollte das Problem lösen.

    Nö, denke ich nicht, wenn ich folgenden Code sehe:

    CMySocket CSocket02Dlg::m_sListenSocket;
    CMySocket CSocket02Dlg::m_sConnectSocket;
    
    unsigned int CSocket02Dlg::TrySocketConnect(LPVOID pParam)
    {
        m_sConnectSocket.SetParent((CDialog *)pParam);
        m_sListenSocket.SetParent((CDialog *)pParam);
    
        //--- Versuchen als Client Verbindung
        //--- zu einem Server zu bekommen
        if(!m_sListenSocket.Create())
            RETAILMSG(1,(_T("m_sListenSocket.Create: %d\n\r"), GetLastError()));
    
        while(!m_sListenSocket.Connect(_T("172.31.255.1"), 6000))
        {
            RETAILMSG(1,(_T("Try to Connect\n\r")));
            Sleep(1000);
        }
    
        RETAILMSG(1,(_T("Connected now!\n\r")));
    
        return 0;
    }
    
    BOOL CSocket02Dlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
    
        AfxBeginThread(TrySocketConnect, (LPVOID)this);
    ...
    ...
    }
    

    Die Konstruktion erfolgt eindeutig außerhalb des Threads. Aber der Ansatz, dass der Create-Aufruf außerhalb des Threads erfolgen sollte, müsste mal getestet werden.



  • Doch, doch. In seiner letzten Implementierung, die er hier gepostet hat, war es mit new drin. Auf diese hab ich mich bezogen.

    Ist aber egal, es hängt höchstwahrscheinlich am Create.



  • So, ich bin wieder einen Schritt weiter. Der Tipp mit dem Create war goldrichtig. Das Create gehört in den Hauptthread, dann geht es.

    Vielen Dank 👍

    Nur einen Sache funktioniert noch nicht. 😞 Wenn die Hostanwendung nun wieder geschlossen wird, soll meine Anwendung wieder pollen und sich wieder verbinden, sobald die Hostanwendung wieder da ist.

    So habe ich es versucht:

    // CMySocket-Memberfunktionen
    
    void CMySocket::SetParent(CDialog * pWnd)
    {
    	m_pWnd = pWnd;
    }
    
    void CMySocket::OnClose(int nErrorCode)
    {
    #ifdef _WIN32_WCE
    	if (INVALID_SOCKET != m_hSocket)
    	{
    		RETAILMSG(1, (_T("AsyncSelect(0);\n")));
    		AsyncSelect(0);   // switch of eventhandling
    	}
    #endif
    
    	RETAILMSG(1, (_T("OnClose:\n")));
    
    	CAsyncSocket::OnClose(nErrorCode);
    
    	if(nErrorCode == 0)
    		((CSocket02Dlg*)m_pWnd)->OnClose();
    }
    
    // Socket02Dlg.cpp : Implementierungsdatei
    //
    
    CMySocket *CSocket02Dlg::m_psListenSocket;
    CMySocket *CSocket02Dlg::m_psConnectSocket;
    
    unsigned int CSocket02Dlg::TrySocketConnect(LPVOID pParam)
    {	
    	while(!m_psListenSocket->Connect(_T("172.31.255.1"), 6000))
    	{
    		if(GetLastError() == WSAEISCONN /* (10056) Socket is already connected. */)
    		{
    			RETAILMSG(1,(_T("GetLastError() == WSAEISCONN -> break\n")));
    			break;
    		}
    
    		RETAILMSG(1,(_T("Try to Connect - Error Code: %d\n"),GetLastError()));
    		Sleep(1000);
    	}
    
    	RETAILMSG(1,(_T("Connected now!\n")));
    
    	return 0;
    }
    
    BOOL CSocket02Dlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	m_psConnectSocket = new CMySocket;
    	m_psListenSocket = new CMySocket;
    
    	m_psConnectSocket->SetParent(this);
    	m_psListenSocket->SetParent(this);
    
    	//--- Versuchen als Client Verbindung 
    	//--- zu einem Server zu bekommen
    	if(!m_psListenSocket->Create())
    		RETAILMSG(1,(_T("m_psListenSocket->Create: %d\n\r"), GetLastError()));
    
    	AfxBeginThread(TrySocketConnect, (LPVOID)this);
    }
    
    void CSocket02Dlg::OnClose()
    {
    	RETAILMSG(1, (_T("CSocket02Dlg::OnClose: \r\n")));
    	m_psConnectSocket->Close();
    	m_psListenSocket->Close();
    
            AfxBeginThread(TrySocketConnect, (LPVOID)this);		
    }
    

    Wird nun also die Verbindung Seitens der Hostanwendung geschlossen, wird das OnClose Event aufgerufen. Dort rufe ich die OnClose Funktion meiner Dialogklasse auf. In dieser starte ich wieder den 'PollThread'.

    Nur wird dann keine Verbindung aufgebaut. Connect kommt immer mit dem ReturnValue WSAENOTSOCK (10038) Socket operation on non-socket. zurück. 😞

    Wo liegt hier nun wieder das Problem?



  • *push*



  • Hat keiner eine Idee?



  • Bin mir nicht ganz sicher, aber du kannst das ja mal versuchen die beiden Close der Sockets wegzulassen, also die in der OnClose deines Dialoges, nicht das der da rum spinnt weil die beiden ja schon geschlossen sind, hatte da was bei MS gelesen, aber ob das auf deinen Fall zutrifft

    http://support.microsoft.com/kb/155738/de

    is aber wie gesagt nur ne dumme idee ob dich das weiter bringt, weis ich nicht


Anmelden zum Antworten