Newsgroup: it.comp.lang.c++
Titolo: Problema con socket

Ciao a tutti. Ho sviluppato un'applicazione MFC per effettuare un 
trasferimento HTTP di un file tra un client ed un server. 
L'applicazione riceve in input un elenco di server da contattare (nella 
fattispecie sono delle centraline remote con un web server locale), e 
uno ad uno invia il file e chiude la connessione. La sequenza di 
operazioni che effettuo è dunque questa:
1) Chiamata dial-up alla centralina X
2) Apertura del socket sulla porta 80
3) HTTP POST del file verso la centralina
4) Ricezione della risposta, per capire se il trasferimento è andato a 
buon fine o meno
5) Apertura di un nuovo socket (dopo la response il socket utilizzato è 
chiuso dalla centralina)
6) HTTP GET della pagina appropriata per confermare le operazioni da 
effettuare post-chiamata
7) Ricezione della risposta e chiusura del socket
8) Chiusura della comunicazione con la centralina
Questi passi vengono ripetuti in sequenza per ogni centralina della 
lista. Il problema è che con la prima centralina viene effettuato tutto 
correttamente, mentre dalla seconda chiamata in poi, ad ogni tentativo 
di richiamare il metodo CSocket.Create() l'applicazione crasha con un 
"Unhandled Exception: Access violation", pur essendo tutto il codice in 
un blocco try-catch.
In step-by-step sono arrivato a vedere che il codice si blocca qui:
* File MAP_PP.cpp
void* CMapPtrToPtr::GetValueAt(void* key) const
// find value (or return NULL -- NULL values not different as a result)
{
	if (m_pHashTable == NULL)    // IL CODICE SI BLOCCA QUI!!!
		return NULL;
	UINT nHash = HashKey(key) % m_nHashTableSize;
	// see if it exists
	CAssoc* pAssoc;
	for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = 
pAssoc->pNext)
	{
		if (pAssoc->key == key)
			return pAssoc->value;
	}
	return NULL;
}
Mentre il codice implicato nelle operazioni sopra elencate è il 
seguente:
* Thread di gestione dell'upload (per semplicità ho rimosso tutti gli 
if e controlli di flusso)
while(Tmp != NULL)
{
  DialUp(Tmp->PhoneNumber);
  CHTTPOnSocket* pClient = NULL;
  pClient = new CHTTPOnSocket();
  pClient->InitializePostArguments();
  pClient->AddPostArgument("FwFile",FwFilename,TRUE);
 
pClient->DoRequest(SERVER_ADDRESS,UPLOAD_FW_PAGE,CHTTPOnSocket::RequestPostMultiPart);
  LPSTR Response = pClient->QueryHTTPResponse();
  pClient->DoRequest(SERVER_ADDRESS, 
UPLOAD_OK_PAGE,CHTTPOnSocket::RequestGet);
  Response = pClient->QueryHTTPResponse();
  HangUp();
  pClient->~CHTTPOnSocket();
  Tmp = Tmp->Next;
}
* Metodi utili della classe CHTTPOnSocket per l'invio/ricezione dati su 
socket.
Socket e SocketFile sono definiti come attributi di classe in 
CHTTPOnSocket.h in questo modo:
CSocket* Socket;
CSocketFile* SocketFile;
CHTTPOnSocket::CHTTPOnSocket()
{
	Socket = NULL;
	SocketFile = NULL;
	AfxSocketInit(NULL);
}
LPSTR CHTTPOnSocket::QueryHTTPResponse()
{
	LPSTR RecBuffer = (LPSTR)::LocalAlloc(LPTR,RECEIVING_BUFFER);
	if(Socket == NULL)
		RecBuffer = NULL;
	else
	{
		try
		{
			CArchive *Receiver = new CArchive(SocketFile,CArchive::load);
			int n = Receiver->Read(RecBuffer,RECEIVING_BUFFER);
			Receiver->Close();
			Receiver->~CArchive();
		}
		catch (CException *e)
		{
			e->Delete();
			RecBuffer = NULL;
		}
		this->CloseSocket();
	}
	return RecBuffer;
}
void CHTTPOnSocket::CloseSocket()
{
	try
	{
		SocketFile->Close();
		SocketFile->~CSocketFile();
		if(Socket != NULL)
		{
			Socket->Close();
			Socket->~CSocket();
		}
	}
	catch (CException *e)
	{
		e->Delete();
	}
	Socket = NULL;
}
BOOL CHTTPOnSocket::DoRequest(LPCSTR ServerAddress, LPCSTR Url, int 
Method)
{
	try
	{
		if(Socket == NULL)
		{
			Socket = new CSocket();
			Socket->Create();
		}
		Socket->Connect(ServerAddress,80);
		SocketFile = new CSocketFile(Socket);
	}
	catch(CException *e)
	{
		e->Delete();
		return FALSE;
	}
	switch(Method)
	{
		case CHTTPOnSocket::RequestGet:
			return this->DoGet(ServerAddress, Url);
			break;
		case CHTTPOnSocket::RequestPost:
			return this->DoPost(ServerAddress, Url);
			break;
		case CHTTPOnSocket::RequestPostMultiPart:
			return this->DoPostMultiPart(ServerAddress, Url);
			break;
		default:
			return FALSE;
			break;
	}
}
BOOL CHTTPOnSocket::DoGet(LPCSTR ServerAddress, LPCSTR Url)
{
	CString UrlToGet;
	try
	{
		CArchive *Sender = new CArchive(SocketFile,CArchive::store);
		UrlToGet.Format("GET /%s HTTP/1.1\r\n\r\n",Url);
		Sender->Write((PBYTE)UrlToGet.GetBuffer(UrlToGet.GetLength()),UrlToGet.GetLength());
		Sender->Flush();
		Sender->Close();
	}
	catch (CException *e)
	{
		e->Delete();
		return FALSE;
	}
	return TRUE;
}
BOOL CHTTPOnSocket::DoPostMultiPart(LPCSTR ServerAddress, LPCSTR Url)
{
	BOOL bRet = FALSE;
	DWORD ContentLengthValue = GetContentLengthValue();
	CString Headers = BuildPostHeaders(Url,ContentLengthValue);
	PBYTE MultipartData;
	MultipartData = (PBYTE)::LocalAlloc(LPTR, ContentLengthValue);
	GetMultipartData(MultipartData,ContentLengthValue);
	PBYTE PostRequest = (PBYTE)::LocalAlloc(LPTR,Headers.GetLength() + 
ContentLengthValue);
	PBYTE Tmp = PostRequest;
	::CopyMemory(Tmp, Headers, Headers.GetLength());
	Tmp += Headers.GetLength();
	::CopyMemory(Tmp, MultipartData, ContentLengthValue);
	// Here, in PostRequest we have the complete request to send to remote 
host
	try
	{
		CArchive *Sender = new CArchive(SocketFile,CArchive::store);
		Tmp = PostRequest;
		Sender->Write((PBYTE)Tmp,Headers.GetLength() + ContentLengthValue);
		Sender->Flush();
		Sender->Close();
		Sender->~CArchive();
		bRet = TRUE;
	}
	catch (CException *e)
	{
		e->Delete();
	}
	return bRet;
}
CHTTPOnSocket::~CHTTPOnSocket()
{
	try
	{
		if(Socket != NULL)
		{
			Socket->Close();
			Socket->~CSocket();
		}
	}
	catch (CException* e) // Socket already closed
	{
		e->Delete();
	}
	Socket = NULL;
	AfxSocketTerm();
}
Il problema si verifica nel metodo DoRequest. Quando viene chiamata la 
seconda centralina, ed eseguita l'istruzione
pClient->DoRequest(SERVER_ADDRESS,UPLOAD_FW_PAGE,CHTTPOnSocket::RequestPostMultiPart);
il programma solleva l'eccezione in
if(Socket == NULL)
{
	Socket = new CSocket();
	Socket->Create();
}
del metodo DoRequest di CHTTPOnSocket...ormai ho tentato di tutto, ma 
non so più che pesci prendere...qualcuno potrebbe darmi una mano??? 
Grazie mille a tutti!
Elvandar

 [CUT]
Ok, non importa...ovviamente prima ho postato sul ng, e poi ho detto 
"facciamo ancora una ricerchina su google gruppi"...ovviamente in 5 
minuti ho risolto!!! E scoperto che è un bug di vc++ 6 fino 
all'sp3...microzozz di m...!!! Vabbè :)
Ciao!

 all'sp3...microzozz di m...!!! Vabbè :)
Tenendo conto che l'ultimo e' il service pack 6 e' di 3 anni fa, e il 
service pack 3 che ti serve e' di 8 anni fa (ovvero e' uscito l'anno 
dopo la pubblicazione del pacchetto originale), vedi tu se e' colpa di 
microsoft, almeno questa volta... =)
--
Marco

Pan formulated the question :

Hai ragione che la versione che sto utilizzando è obsoleta e avrei 
dovuto installare il service pack prima (anche se purtoppo non mi è 
possibile, il capo è sempre il capo...), ma considerando che il vc++ 5 
non presentava questo problema, ed il codice girava senza 
problemi...sì, almeno in parte è colpa di microsoft ;)
Ciao!