POP3 E-Mail Thread [DRINGEND!]



  • Hallo Leute ich habe wiedermal ein Problem.

    Und zwar muss ich heute noch meine Projektarbeit fertig kriegen,die sowäre ein MultiUser E-Mail Client.

    Hab alles fertig Userverwaltung etc, wirklich alles gestern Abend kam ich dann dazu einen Thread zubasteln mit dem ich die emails an den POP3 Server abholen will und genau dabai hab ich ein rießen konflikt im Hirn.

    Ich erstelle also einen Thread, in diesem Lasse ichfür jeden POP3Server ein Socket erstellen und will dort nun die mails abfragen.
    Ich habe eine Klasse CSendSocket vom Typ CAsyncSocket.

    in meiner App:

    //Pseudocode
    PtrArray(CSendSOcket*) pSpckets; //Pseudocode, hab halt ein CPtrArray vom Typ CSendSocket!
    
    //Pseudocode...
    im thread::InitInstance()
    {
       for(int x=0;x<POP3Serrvers;x)
       {
          CSendSocket *tmpServer = new CSendSocket;
          tmpServer->Create();
          tmpServer->iPos=x;//benutze ich um im Socketselber nacher zu wissen welches socket gerade läuft im CPtrArray
          tmpServer->Start();
          theApp.pSockets.Add(tmpServer);
       }
    
       bool AllFinish=false;
       while(!AllFinish)
       {
           AllFinish=true;
           for(int x=0;x<theApp.pSockets.GetCount();x++)
           {
              if(theApp.pSockets[x]->bfinished!=true)
                 AllFinish=false;
           }
       }
    }
    

    in der Klasse CSendSocket hab ich ne bool bfinished, diese soll gesetz werden wenn das socket die kommunikation mit dem POP3 serverabgeschlossen hat.

    Das Problem ist, dass Mein Programm die Funktion start vom socket zwar aufruft,dann aber gleich in die while(!AllFini) Schleife reinspringt, und das socket in der Zeit nicht mehr weiter arbeiten lässt, heißt er frägt ständig ab ob die Sockets fertig sind,lässt sie aber nicht weiter laufen um überhaupt fertig zu werden.

    Bitte helft mir, wie kann ichd as realisieren, ich muss die Kommunikation (Protokoll) selber realisiren,also es sind mir keine fertigen klassen erlaubt.

    Und ich muss das dringend hin kriegen, wie kann ich das machen, Beispiele, hilfe theorie ansätze ich bin für ALLES dankbar!

    mfb BigMama



  • Push

    Kann Mir denn keiner hier helfen?



  • Warum willst du das Rad neu erfinden. Nimm eine vorhandene Klasse.
    http://www.naughter.com/



  • ich muss das leider tun ist mir in der projektarbeit so auferlegt worden



  • Unix-Tom schrieb:

    Warum willst du das Rad neu erfinden. Nimm eine vorhandene Klasse.
    http://www.naughter.com/

    Vielleicht deshalb?

    bigmama schrieb:

    Bitte helft mir, wie kann ichd as realisieren, ich muss die Kommunikation (Protokoll) selber realisiren,also es sind mir keine fertigen klassen erlaubt.

    Allderings *gesteh* könnte man da mal nachschauen, wie's gemacht wird.

    @bigmama:
    Versuch mal ein Sleep(10) oder so am Ende der while-Schleife, vielleicht kommt er ob der Prozessorlast nicht mehr dazu, die anderen Threads ran zu lassen.
    Gruss,
    Qweety.



  • ich dachte bisher immer das dadurch dass er in der while ist, also das Programm steckt akt. in der while schleife also kann es ja nicht gleichzeitig ind er socket klasse sein?



  • Hi,
    ich bin mir auch nicht sicher, aber immer wenn irgendwas mit mehreren Threads passiert, muss man im Thread dafür Sorge tragen, dass der auch mal Pause macht.

    Bin mir wie gesagt, nicht sicher, dass es das ist. Macht denn CSendSocket::Start nen Thread auf, oder nicht?
    Weil, wenn die Sockets nicht arbeiten, während Du in der while-Schleife bist, kann sich ja auch nix ändern.

    Gruss,
    Qweety.

    P.S.
    Wenn es an sowas liegt, sieht man's meistens im TaskManager, while die Systemlast auf 100 pro geht.



  • also ich bin ja jetzt zu hause und kann mal die sources rein pasten,

    relevant in der App:

    CTypedPtrArray<CObArray, CSendSocket*> pSockets;
    

    dann wenn man auf emails empfangen drückt:

    CGetMailThread *m_pThread;
    	m_pThread = (CGetMailThread*) AfxBeginThread(RUNTIME_CLASS(CGetMailThread), THREAD_PRIORITY_NORMAL,0, CREATE_SUSPENDED);
    	m_pThread->ResumeThread();
    

    der thread:
    HEADER

    #pragma once
    #include "BlueMail.h"
    #include "SendSocket.h"
    
    // CGetMailThread
    
    class CGetMailThread : public CWinThread
    {
    	DECLARE_DYNCREATE(CGetMailThread)
    
    protected:
    	CGetMailThread();           // protected constructor used by dynamic creation
    	virtual ~CGetMailThread();
    
    public:
    	virtual BOOL InitInstance();
    	virtual int ExitInstance();
    	//CSendSocket *Server;
    
    protected:
    	DECLARE_MESSAGE_MAP()
    };
    

    Die CPP File

    // GetMailThread.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "BlueMail.h"
    #include "GetMailThread.h"
    
    // CGetMailThread
    
    IMPLEMENT_DYNCREATE(CGetMailThread, CWinThread)
    
    CGetMailThread::CGetMailThread()
    {
    }
    
    CGetMailThread::~CGetMailThread()
    {
    }
    
    BOOL CGetMailThread::InitInstance()
    {
    	AfxSocketInit();
    	theApp.pSockets.RemoveAll();
    	bool AllFini=false;
    	CSendSocket *m_sSend = new CSendSocket;
    	m_sSend->Create();
    	m_sSend->iPos=0;
    	m_sSend->Connect("127.0.0.1",25);
    	theApp.pSockets.Add(m_sSend);
    	theApp.pSockets[0]->Start();
    	//AfxMessageBox("g");
    
    	while(!AllFini)
    	{
    		AllFini=true;
    		for(int x=0;x<theApp.pSockets.GetCount();x++)
    		{
    			if(theApp.pSockets[x]->bfinish!=true)
    				AllFini=false;
    		}
    		Sleep(100);
    	}
    
    	for(int x=0;x<theApp.pSockets.GetCount();x++)
    		{
    			theApp.pSockets[x]->Close();
    			delete theApp.pSockets[x];
    		}
    	AfxMessageBox("Thread Ende");
    	return TRUE;
    }
    
    int CGetMailThread::ExitInstance()
    {
    	// TODO:  perform any per-thread cleanup here
    	return CWinThread::ExitInstance();
    }
    
    BEGIN_MESSAGE_MAP(CGetMailThread, CWinThread)
    END_MESSAGE_MAP()
    
    // CGetMailThread message handlers
    

    und nun noch die klasse CSendSocket : public CAsyncSocket
    HEADER

    #pragma once
    #include "BlueMail.h"
    
    // CSendSocket command target
    
    class CSendSocket : public CAsyncSocket
    {
    public:
    	CSendSocket();
    	virtual ~CSendSocket();
    
    	void OnClose(int nErrorCode);
    	void OnReceive(int nErrorCode);
    	void OnSend(int nErrorCode);
    	void OnConnect(int nErrorCode);
    	void Start();
    	int AuthOK;
    
    	CString strServer;
    	int iPort;
    	CString strUser;
    	CString strPass;
    	bool bfinish;
    	int iPos;
    };
    

    und die CPP:

    // SendSocket.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "BlueMail.h"
    #include "SendSocket.h"
    
    // CSendSocket
    
    CSendSocket::CSendSocket()
    {
    	strServer="";
    	iPort=110;
    	strUser="";
    	strPass="";
    	bfinish=false;
    	iPos=0;
    }
    
    CSendSocket::~CSendSocket()
    {
    	Close();
    }
    
    void CSendSocket::OnConnect(int nErrorCode)
    {
    	if (0 != nErrorCode)
       {
          switch( nErrorCode )
          {
             case WSAEADDRINUSE: 
                AfxMessageBox("The specified address is already in use.\n");
                break;
             case WSAEADDRNOTAVAIL: 
                AfxMessageBox("The specified address is not available from the local machine.\n");
                break;
             case WSAEAFNOSUPPORT: 
                AfxMessageBox("Addresses in the specified family cannot be used with this socket.\n");
                break;
             case WSAECONNREFUSED: 
                AfxMessageBox("The attempt to connect was forcefully rejected.\n");
                break;
             case WSAEDESTADDRREQ: 
                AfxMessageBox("A destination address is required.\n");
                break;
             case WSAEFAULT: 
                AfxMessageBox("The lpSockAddrLen argument is incorrect.\n");
                break;
             case WSAEINVAL: 
                AfxMessageBox("The socket is already bound to an address.\n");
                break;
             case WSAEISCONN: 
                AfxMessageBox("The socket is already connected.\n");
                break;
             case WSAEMFILE: 
                AfxMessageBox("No more file descriptors are available.\n");
                break;
             case WSAENETUNREACH: 
                AfxMessageBox("The network cannot be reached from this host at this time.\n");
                break;
             case WSAENOBUFS: 
                AfxMessageBox("No buffer space is available. The socket cannot be connected.\n");
                break;
             case WSAENOTCONN: 
                AfxMessageBox("The socket is not connected.\n");
                break;
             case WSAENOTSOCK: 
                AfxMessageBox("The descriptor is a file, not a socket.\n");
                break;
             case WSAETIMEDOUT: 
                AfxMessageBox("The attempt to connect timed out without establishing a connection. \n");
                break;
             default:
                TCHAR szError[256];
                wsprintf(szError, "OnConnect error: %d", nErrorCode);
                AfxMessageBox(szError);
                break;
          }
          AfxMessageBox("Please close the application");
       }
    	CAsyncSocket::OnConnect(nErrorCode);
    }
    
    void CSendSocket::OnClose(int nErrorCode)
    {
    	CAsyncSocket::OnClose(nErrorCode);
    }
    
    void CSendSocket::OnSend(int nErrorCode)
    {	
    	CAsyncSocket::OnSend(nErrorCode);
    }
    
    void CSendSocket::OnReceive(int nErrorCode)
    {	
    	char *pBuf = new char[1025];
    	int iBufSize = 1024;
    	int iRcvd;
    	CString strRecvd;
    
    	iRcvd = theApp.pSockets[iPos]->Receive(pBuf,iBufSize);
    	pBuf[iRcvd] = '\0';
    	strRecvd = pBuf;
    	int checker=0;
    		for(int bla=0;bla<strRecvd.GetLength();bla++)
    		{
    			checker++;
    			if(checker==100)
    			{
    				strRecvd.Insert(bla,"\n");
    				checker=0;
    			}
    		}
    	AfxMessageBox("Empfangen\n"+strRecvd);
    	theApp.pSockets[iPos]->Send("PASS XYZ\n",15);
    	bfinish=true;
    	CAsyncSocket::OnReceive(nErrorCode);
    }
    
    void CSendSocket::Start()
    {
    	theApp.pSockets[iPos]->Send("USER XYZ\n",20);
    
    }
    

    Somit wären alle Fragen beantwortet.
    also zum Thema Threat, hab da jetzt mal nen Sleep rein aber der häält ja soweit ich weis die ganze exe, also den ganzen Prozess an, also alles, auch das Socket?



  • Nein, der hält nur den Thread an. Zumindest bei meinem neuen Socket, den ich so laufen hab.

    Ich schicke da auch Daten los und warte in einer while-Schleife auf Antwort, derweil im Socket fleissig gehorcht wird. Anders würde es ja auch gar nicht gehen.

    Das mit dem Sleep habe ich mir von http://www.henkessoft.de abgeschaut. Als ich das MFC-Tut durchgearbeitet hab' da hat bei mir auch immer alles stillgestanden, wenn man das Sleep weggelassen hat. Der hier im Forum auch bekannte Author hat das mit dem Multithreading ganz gut beschrieben *find*.

    Aber wenns daran nicht lag, dann lags nicht daran. Ich schau mal durch die Sourcen, aber da brauch ich was für. Vielleicht findet ja nun auch ein anderer was.
    Bis dann.
    Qweety.

    P.S.
    Das Connect von CAsynchSocket müsste dann eigentlich den Thread machen und dann die Events erzeugen.



  • wie meinst du das connect müsste die threads erzeugen?
    was würde dann der thread amchen, der thread kann ja nicht die messages vom socket handeln?



  • Hi,
    also ich habe den Socket von ihm hier verwendet:
    http://www.codeproject.com/internet/serversocket.asp.
    Das vebindet man sich zunächst auf Server und Port und dann ruft man
    eine Funktion WatchComm auf (kann heissen wie sie will), und die eröffnet dann den Lauschthread auf die Verbindung.

    Wenn dann Daten eingehen, werden irgendwelche Eventhandler aufgerufen.

    Wenn ich Deine Start-Funktion richtig interpretiere, dann sendest Du da ja schon Daten und wartest dann auf die Antwort.

    Du würdest aber nie eine Antwort bekommen, wenn nicht zeitgleich in einem anderen Thread auch jemand auf die Verbindung horcht und im Falle des Dateneinangs agiert. Irgendwer muss ja während Deiner while-Schleife

    theApp.pSockets[x]->bfinished
    

    auf true setzen.

    Also wenn Du mal mit Spy++ oder dem ProcessViewer (zumindest beim VS6 gibbet den noch) schaust, nüsste Deine Anwendung mehr als einen Thread haben, sobald die Verbindung zum Socket erfolgreicht ist.

    Nun war meine Vermutung, dass der aber nie zum lauschen kommt, while Deine while-Schleife ja nie ne Pause macht.

    Die Funktion Start ist längst zurück, die kann nix mehr machen.

    Wenn das aber nichts gebracht hat, muss es an was anderem liegen. Ich muss aber nun auch los, von daher kann ich heute nicht mehr weitesuchen.
    Sorry. Hab's versucht.

    Viel Erfolg, vielleicht weiss ja wer anders Rat.

    Gruss,
    Qweety.



  • Danke Qweety für deine Hilfe, ich habe mal das Thread Tutorial durchgelesen udn dadurch klingt was du sagst auch sehr plausibel.

    Aber ich hab trozdem noch eine Frage zum Socket Prinzip.
    Ich connecte in meinem thread zum server, dann rufe ich die Start Funktion auf,a lso sende ein "hallo" an den Server, bin ich zu der zeit etwa nicht mit dem Server verbunden? Habe doch vorher Connect durchgeführt, oder muss ich dessen Antwort auf mein Connect, sprich in meinem Socket mit onAccept() dessen Verbindung erst übernehmen?

    Weil ich weis nicht ob du das falsch verstanden hast, ich bin ja kein Server der auf eine eingehende Verbindung wartet, ich bin der Client.


Anmelden zum Antworten