Socket blockiert



  • Hallo
    ich schreibe gerade an einem Programm, bei dem ich eine Testnachricht an einen Server sende.
    Problem: Die erste Nachricht geht noch. Dann schließe ich den Socket der die Nachricht geschickt hat (macht wenig Sinn aber es is zum Testen), ich bekomm beim Server die Nachricht das der Socket den ich bei WM_ACCEPT übergeben hab geschlossen werden will, schließe auch den. Aber trotzdem bleibt bei netstat -a der Socket der die Nachricht geschickt hat bestehen mit dem Zustand WARTEND. Ziemlich ärgerlich, weil ich will mich zu einem anderen Server verbinden, aber da der andere noch WARTEND ist kann ich natürlich den neuen Socket nicht mehr erstellen (Port schon belegt) 😡 .
    Kann mir jemand sagen wie ich den wartenden Socket beenden kann ?



  • ohne code ist die einzige diagnose die ich abgeben kann:
    wird schon so passen, sonst würds net so sein



  • Naja, den Code kann ich ja mal posten, aber ob das soviel bringt:
    Ansehen sollte man die Funktionen SendTest(CString IP) (Damit teste ich ob ich eine Verbindung zum Server aufbauen kann) und MsgSocketFunc (da die Zeile mit case WM_SCK_CLOSE, da schließ ich den Socket von WM_SCK_ACCEPT)

    Vielleicht kann mir auch jemand sagen, wie ich den Timeout für eine Verbindung setzen kann. Vielleicht bringt das etwas.
    Irgendwie bleibt der Socket auch noch WARTEND wenn ich das Programm beendet hab, obwohl er eigentlich mit delete schon im Nirvana sein sollte

    // REMConnection.cpp: Implementierung der Klasse REMConnection.
    //
    //////////////////////////////////////////////////////////////////////
    
    /*Hinweis: Diese Klasse funktioniert mit CXSocket
    CXSocket ist nur eine Ableitung von CSocket
    nur dass CXSocket eine globale Funktion aufruft wenn eine Nachricht ankommt*/
    
    #include "stdafx.h"
    #include "stdafx.h"
    #include "REMConnection.h"
    
    #ifdef _DEBUG
    #undef THIS_FILE
    static char THIS_FILE[]=__FILE__;
    #define new DEBUG_NEW
    #endif
    
    //////////////////////////////
    //auf ein paar umwegen die Klassenfunktion aufrufen -> Es darf nur ein REMConnection Objekt existieren:
    CREMConnection *pTheOnlyREMCon=NULL;
    
    void SetOnlyREMConnection(CREMConnection *REMCon)
    {
    	if(pTheOnlyREMCon!=NULL) //Oh,oh es existiert schon eine!!!!
    	{
    		TRACE0("Es darf nur ein REMConnection-Objekt im Programm geben!!!!");
    		ASSERT(FALSE); //Tja
    	}
    
    	ASSERT(REMCon!=NULL); //das is nun wirklich dumm....
    
    	pTheOnlyREMCon=REMCon;
    }
    
    void glblXSockMsgFunc(int sock_msg,int error,int ID,int lParam,int wParam)
    {
    	ASSERT(pTheOnlyREMCon!=NULL); //ja das sollt es nicht sein
    	pTheOnlyREMCon->MsgSocketFunc(sock_msg,error,ID,lParam,wParam);
    }
    
    //////////////////////////////////////////////////////////////////////
    // Konstruktion/Destruktion
    //////////////////////////////////////////////////////////////////////
    
    CREMConnection::CREMConnection()
    {
    	MyIP="0.0.0.0";
    
    	CountSockets=ActiveSockets=0;
    	ppSockets=NULL;
    	pServerSocket=NULL;
    	pParentWnd=NULL;
    
    	SetOnlyREMConnection(this);
    }
    
    CREMConnection::~CREMConnection()
    {
    	DeleteSocketsPointer();
    
    	if(pServerSocket!=NULL)
    	{
    		pServerSocket->Close();
    		delete pServerSocket;
    	}
    }
    
    //Diese Funktion bekommt alle Nachrichten von den Sockets die erstellt wurden
    void CREMConnection::MsgSocketFunc(int sock_msg,int error,int ID,int lParam,int wParam)
    {
    	TRACE2("[CREMConnection]: Habe vom Socket %i eine Nachricht erhalten! Msg-Nummer: %i\n",ID,sock_msg);
    	TRACE1("Nachricht: %s\n",CXSocketWM2String(sock_msg));
    
    	if(ID==-1) //Server spricht zu uns
    	{
    		TRACE0("[CREMConnection] Nachricht für Server angekommen!\n");
    		if(sock_msg==WM_SCK_ACCEPT)
    		{
    			CXSocket *pNewSocket=CreateNewSocket();
    			pNewSocket->m_State=SCK_CLIENT;
    			if(pServerSocket->Accept(*pNewSocket))
    				TRACE1("[CREMConnection]: Eine Verbindung wurde über Socket mit ID %i aufgebaut!\n",pNewSocket->m_ID);
    			else
    				TRACE0("[CREMConnection]: Der Server konnte keine Verbindung aufbauen!!!!!\n");
    		}
    	}
    	else //Alle anderen behandeln
    	{
    		ASSERT(ID<CountSockets);
    		CXSocket *pMsgSocket=ppSockets[ID];
    
    		//Deklaration aller Variablen in switch
    		int n=0; //n zum zählen
    		//case WM_SCK_RECEIVE:
    		int rec_size=0; //größe von empfangener bytes			
    		char rec_buffer[1024];
    
    		int real_size=0; //Anzahl empfangener Bytes
    		char *bytes=NULL;
    		char *sav_buffer=NULL;
    
    		char rem_msg;
    		//end case WM_SCK_RECEIVE
    
    		switch(sock_msg)
    		{
    		case WM_SCK_RECEIVE:			
    
    			do
    			{
    				rec_size=pMsgSocket->Receive(rec_buffer,sizeof(rec_buffer));
    				if(rec_size==0)
    					break; //Abbruch!
    
    				if(bytes!=NULL) //Abspeichern des Puffers
    				{
    					sav_buffer=new char[real_size];
    					memcpy(sav_buffer,bytes,real_size);
    
    					delete [] bytes;
    					bytes=new char[real_size+rec_size]; //Platz für die nächsten Bytes
    
    					memcpy(bytes,sav_buffer,real_size); //Alte Bytes vom Buffer in den neuen
    				}//Geschafft!!!
    				else
    					bytes=new char[rec_size];
    
    				memcpy(&bytes[real_size],rec_buffer,rec_size); //Neue Bytes anhängen
    
    				real_size+=rec_size;
    			}
    			while(!(rec_size<sizeof(rec_buffer)));
    
    			TRACE1("%i Bytes empfangen...\n",real_size);
    
    			//Nachrichtenanalyse:
    
    			rem_msg=bytes[0]; // Nachrichtennummer steht an erster Stelle
    
    			switch(rem_msg) //nochmal switch.... oh gott
    			{
    			case REM_MSG_TEST:
    				TRACE0("[CREMConnection]:Testnachricht erhalten!\n");
    				CallREMMsgArrived(0,0);
    				delete [] bytes;
    				break;
    
    			default:
    				TRACE0("Unbekannte REM-Nachricht erhalten!!!\n");
    				delete [] bytes; //ab in den Abfalleimer
    				break;
    			} // oje oje, das wird noch ne Arbeit
    
    			break; //und raus aus switch!!!!
    			//end WM_SCK_RECEIVE
    
    			case WM_SCK_CLOSE:
    				ppSockets[ID]->Close();
    				TRACE0("Socket geschlossen!\n");
    				break;
    
    		default:
    			TRACE0("Socketnachricht nicht behandelt!!!! (oder brake vergessen)\n");
    			break;
    		}
    	}
    
    }
    
    CXSocket* CREMConnection::CreateNewSocket()
    {
    	CXSocket **ppSocketsBuffer;
    	ppSocketsBuffer=new CXSocket*[CountSockets+1];
    
    	if(CountSockets>0)
    	{
    		memcpy(ppSocketsBuffer,ppSockets,CountSockets*sizeof(void*)); //Alle Zeiger in den Buffer kopieren
    		delete [] ppSockets; //Zeiger-Array löschen
    	}
    
    	ppSocketsBuffer[CountSockets]=new CXSocket; //Neuer Socket
    	ASSERT(ppSocketsBuffer[CountSockets]!=NULL);
    	ppSocketsBuffer[CountSockets]->SetMsgSocketFunc(&glblXSockMsgFunc);
    	CountSockets++;
    
    	ppSockets=ppSocketsBuffer; //ppSockets zeigt jetzt auf den Buffer
    
    	//So vom Speicher her alles erledigt, jetzt kommt REM
    	ppSockets[CountSockets-1]->m_ID=CountSockets-1; //So bekommt jeder eine ID die seinem Platz im Array entspricht
    
    	TRACE2("[CREMConnection::CreateNewSocket] Socket mit der Adresse 0x%X und der ID %i erstellt!\n",ppSockets[CountSockets-1],ppSockets[CountSockets-1]->m_ID);
    
    	return ppSockets[CountSockets-1]; //letzten = neuer Socket zurückgeben
    }
    
    void CREMConnection::DeleteSocketsPointer()
    {
    	if(CountSockets>0)
    	{
    		for(int n=0;n<CountSockets;n++)
    		{
    			ppSockets[n]->Close();
    			delete ppSockets[n];
    		}
    
    		delete [] ppSockets;
    	}
    }
    
    CXSocket* CREMConnection::GetSocket(int ID)
    {
    	if(ID==-1)
    		return pServerSocket;
    	else
    		ASSERT(ID>0);
    
    	CXSocket* pSock=ppSockets[ID];
    
    	return pSock;
    }
    
    BOOL CREMConnection::CreateServer() //Erstellt einen Server-Socket. Dieser aktzeptiert Verbindungen und gibt diese an einen anderen Socket ab!
    {
    	pServerSocket=new CXSocket;
    	ASSERT(pServerSocket);
    
    	if(!pServerSocket->Create(REM_PORT_SERVER))
    	{
    		TRACE0("[CREMConnection::CreateServer()]: Erstellen fehlgeschlagen! Create gab FALSE zurück!\n");
    		return FALSE;
    	}
    	if(!pServerSocket->Listen())
    	{
    		TRACE0("[CREMConnection::CreateServer()]: Erstellen fehlgeschlagen! Listen gab FALSE zurück!\n");
    		return FALSE;
    	}
    
    	pServerSocket->SetMsgSocketFunc(&glblXSockMsgFunc);
    	pServerSocket->m_State=SCK_SERVER;
    	pServerSocket->m_ID=-1;
    
    	TRACE0("CREMConnection: Server erstellt!\n");
    
    	return TRUE;
    }
    
    BOOL CREMConnection::SendTest(CString IP)
    {
    	CXSocket *pTestSocket=CreateNewSocket();
    	if(!pTestSocket->Create(REM_PORT_CLIENT))
    	{
    		TRACE0("[CREMConnection::SendTest]: Erstellen des Test-Sockets fehlgeschlagen!\n");
    		TRACE1("Fehlernummer: %i\n",GetLastError());
    		return FALSE;
    	}
    
    	TRACE1("Test-Socket mit ID %i erstellt!\n",pTestSocket->m_ID);
    
    	if(!pTestSocket->Connect(IP,REM_PORT_SERVER))
    	{
    		TRACE0("[CREMConnection::SendTest]: Verbinden des Test-Sockets fehlgeschlagen!\n");
    		TRACE1("Fehlernummer: %i\n",GetLastError());
    		return FALSE;
    	}
    
    	char test[]={REM_MSG_TEST,'T','E','S','T','\0'};
    	if(pTestSocket->Send(test,sizeof(test))==-1)
    	{
    		TRACE0("[CREMConnection::SendTest]: Nachricht konnte nicht abgeschickt werden!\n"); 
    		return FALSE;
    	}
    
    	pTestSocket->Close();
    
    	return TRUE;
    }
    
    void CREMConnection::CallREMMsgArrived(int lParam,int wParam)
    {
    	ASSERT(pParentWnd!=NULL);
    	ASSERT(pParentWnd->m_hWnd!=NULL);
    
    	pParentWnd->SendMessage(WM_REM_MSG,lParam,wParam);
    }
    
    void CREMConnection::SetParentWnd(CWnd *pWnd)
    {
    	ASSERT(pWnd!=NULL);
    
    	if(pWnd!=NULL)
    		TRACE0("[CREMConnection::SetParentWnd]: ParentWnd geändert!\n");
    	pParentWnd=pWnd;
    }
    

Anmelden zum Antworten