Discussione: [c++] socket...
View Single Post
Old 21-10-2006, 01:34   #2
-fidel-
Senior Member
 
L'Avatar di -fidel-
 
Iscritto dal: Jan 2006
Messaggi: 2722
Beh sì, il client non è molto elegante... A parte il fatto che, nel main del client, non controlli in valore tornato dalla tua funzione InitClientSocket(), quindi non sai se il socket è stato creato con successo, esso non viene comunque creato con successo
Ti faccio notare che, dal momento che passi alla suddetta funzione un IP in formato puntato (nel tuo caso chiami "InitClientSocket("127.0.0.1", 1000);"),
ti conviene fare, al posto della riga 118 di sock.cpp:

Codice:
if ((saClient.sin_addr.s_addr = inet_addr(pHost) == INADDR_NONE)
{
      // Gestione errore di ip non valido.
	return NULL;
}
così fai pure il controllo di errore sull'ip passato come parametro.
Infatti usare una "gethostbyname()" su un indirizzo ip è praticamente inutile (anche se nessuno ce lo vieta...), dal momento che la funzione serve appunto per convertire un nome host in un indirizzo ip...
Comunque, possiamo anche supporre di non sapere se il parametro pHost sia un nome host o un indirizzo in notazione puntata. Un modo a mio parere "elegante" di gestire la situazione (anche come velocità di esecuzione), può essere la seguente:
Codice:
#define MAX_BUFLENGTH 256

...

saClient.sin_family = AF_INET;
saClient.sin_port = htons(iPort);
if (isalpha(pHost[0]))
{
	// Rimuovo lo '\n' se presente.
	if (pHost[strlnen(pHost, MAX_BUFLENGTH) - 1] == '\n')
		pHost[strnlen(pHost, MAX_BUFLENGTH) - 1] = '\0'; 
	pHostinfo = gethostbyname(pHost);
	if (pHostinfo == NULL)
	{
		// Eventuale gestione errore...
		return NULL;
	}
	// NOTA: nella definizione di sockaddr_in, h_addr = h_addr_list[0]
	//       h_addr è presente solo per retrocompatibilità, meglio non usarlo...
	char *ip = inet_ntoa (*(struct in_addr *)pHostinfo->h_addr_list[0]);
	if (ip == NULL)
	{
		// Eventuale gestione errore...
		return NULL;
	}
	if ((saClient.sin_addr.s_addr = inet_addr(ip) == INADDR_NONE)
	{
		// Eventuale gestione errore...
		return NULL;
	}
}
else
	if ((saClient.sin_addr.s_addr = inet_addr(pHost) == INADDR_NONE)
	{
		// Eventuale gestione errore...
		return NULL;
	}
 ...
Se vuoi invece un codice più compatto ma meno efficiente (usando sempre e solo "gethostbyname()", come dicevo prima nessuno te lo vieta, anche se è uno spreco di tempo e di risorse, seppur *minimo* - ma stiamo sottilizzando ), puoi fare così:

Codice:
#define MAX_BUFLENGTH 256

...

saClient.sin_family = AF_INET;
saClient.sin_port = htons(iPort);
// Rimuovo lo '\n' se presente.
if (pHost[strlnen(pHost, MAX_BUFLENGTH) - 1] == '\n')
	pHost[strnlen(pHost, MAX_BUFLENGTH) - 1] = '\0'; 
pHostinfo = gethostbyname(pHost);
if (pHostinfo == NULL)
{
	// Eventuale gestione errore...
	return NULL;
}
// NOTA: nella definizione di sockaddr_in, h_addr = h_addr_list[0]
//       h_addr è presente solo per retrocompatibilità, meglio non usarlo...
char *ip = inet_ntoa (*(struct in_addr *)pHostinfo->h_addr_list[0]);
if (ip == NULL)
{
	// Eventuale gestione errore...
	return NULL;
}
if ((saClient.sin_addr.s_addr = inet_addr(ip) == INADDR_NONE)
{
	// Eventuale gestione errore...
	return NULL;
}
Del resto, il tuo codice originale (sempre la linea 118), è
Codice:
saClient.sin_addr=*((struct in_addr *)pHostinfo->h_addr);
Cerca di capire da solo perché non va bene.
Ah, ricordati ogni tanto di fare un po' di controllo errori eh!

EDIT: Nel codice che ho postato, ho lasciato i nomi delle variabili identiche a quelle presenti nel codice da te allegato. Quindi puoi fare anche un mero copia-incolla, ma ti consiglio sempre di analizzare il tutto prima
__________________

- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale.
- A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson

Ultima modifica di -fidel- : 21-10-2006 alle 02:16.
-fidel- è offline   Rispondi citando il messaggio o parte di esso