View Full Version : [c++] socket...
vi allego due stupidissimi programmi che dovrebbero fare uno stupidissimo collegamento server/client in cui il client manda al server il messaggio "ciao!", ma sto ciao non arriva :muro: :muro:
ps: ho provato a connettermi al server con
TELNET 127.0.0.1 1000
e se gli mando qualche stringa la legge perfettamente...
quindi credo che il problema sia nel client!!!! :cry:
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:
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:
#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ì:
#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), è
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 ;)
vi allego due stupidissimi programmi che dovrebbero fare uno stupidissimo collegamento server/client in cui il client manda al server il messaggio "ciao!", ma sto ciao non arriva :muro: :muro:
ps: ho provato a connettermi al server con
TELNET 127.0.0.1 1000
e se gli mando qualche stringa la legge perfettamente...
quindi credo che il problema sia nel client!!!! :cry:
Per comunicare non aprire mai porte al di sotto della 1025 perchè fino alla 1024 sono porte usate dal SO.
io ho usato la 12345 e funziona tutto a meraviglia stampa in modo sleeppato il numero 5 ... bravo mamo139...
non ti complicare troppo la vita per vedere il ciao fai queste modifiche:
1. metti come porta 12345 sul client e il server
2. correggi:
// int x = SendTo(sock, "ciao!");
int x = send(sock, "ciao!", 5, 0);
3. correggi:
if (recv(ClientSock,pBuffer, 5, 0) == SERVER_SOCKET_ERROR){
ClientConnesso = false;
continue;
}
pBuffer[5]= '\0';
printf("the message is: %s",pBuffer);
#ifdef DEBUG_MODE
// printf("the message is: %s",pBuffer);
//MessageBox(NULL, pBuffer, "Protocollo", MB_OK);
#endif
N.B. togli i void che non servono.
in + chi legge i listati non capisce quale è il client e il server, indenta il code.
vatti a studiare:
RecvFrom, recv
SendTo, send
SOCK_STREAM o SOCK_DGRAM
IPPROTO_TCP ecc ecc
UDP TCP... ti dice nulla?
x il resto n.d.r
Per comunicare non aprire mai porte al di sotto della 1025 perchè fino alla 1024 sono porte usate dal SO.
Eh? :eek: Nessuno ti vieta di usarle. Se vuoi implementare un server HTTP ad esempio, che porta useresti?
io ho usato la 12345 e funziona tutto a meraviglia stampa in modo sleeppato il numero 5 ... bravo mamo139
x il resto n.d.r
Ma il problema è che il server deve ricevere la stringa "ciao!" e non la riceve con quel codice........
Mi sa che non hai afferato il problema.
Comunque l'errore più grosso (che pregiudica il funzionamento) è quello che ho esposto prima.
Eh? :eek: Nessuno ti vieta di usarle. Se vuoi implementare un server HTTP ad esempio, che porta useresti?
si giusto ma vedendo il codice lui usa un collegamento non sulla 80.
Ma il problema è che il server deve ricevere la stringa "ciao!" e non la riceve con quel codice........
Mi sa che non hai afferato il problema.
Comunque l'errore più grosso (che pregiudica il funzionamento) è quello che ho esposto prima.
Mentre tu hai postato io stavo facendo un Edit al mio messaggio... infatti stampava solo il numero 5 con porta sopra la 1024 mentre non mi ero accorto della stringa ciao.
Cmq non passando per:
int RecvFrom(SOCKET s, char *pBuffer)
... e usando una recv e una send risolve il problema.
@ mamo:
Se può interessarti, visita questo thread:
http://www.hwupgrade.it/forum/showthread.php?t=1138765&page=1&pp=20
Oltre al fatto che la sua lettura penso possa esserti di aiuto, nel mio post #29 trovi allegati un client ed un server, precompilati e con sorgenti ampiamente (ma davvero ampiamente :D) commentati.
Magari possono esserti di ulteriore aiuto.
Mi pare che in quelli non uso la gethostbyname, perchè richiedevo come parametro del client l'ip del server. Puoi provare a prendere quel codice e modificarlo inserendo la gethostbyname() (con uno dei due metodi esposti nel mio precedente post).
si giusto ma vedendo il codice lui usa un collegamento non sulla 80.
Ho fatto l'esempio dell'HTTP, ma può essere qualunque porta <= 1024. In soldoni, il fatto che usi la porta 1000 non è la causa del problema...
Cmq non passando per:
int RecvFrom(SOCKET s, char *pBuffer)
... e usando una recv e una send risolve il problema.
Ma lui sulla RecvFrom non ha problemi, è il client che non va (la SendTo che ha scritto può andare, si può fare di meglio ma funziona).
Ripeto, il problema e su saClient.sin_addr....
Ma lui sulla RecvFrom non ha problemi, è il client che non va (la SendTo che ha scritto può andare, si può fare di meglio ma funziona).
Ripeto, il problema e su saClient.sin_addr....
io nel codice postato sopra, per farlo andare, ho fatto solo quelle modifiche che ho scritto. In particolare send e recv e spostato il printf oltre alla porta.
sulla Client.sin_addr.. nessun problema visto che il "ciao!" arriva.
su 127.0.0.1 in locale funziona.
Forse intendi che con ip dinamico avrebbe dei problemi? invece che 127.0.0.1?
Bene, ho provato a compilare ed usare il codice postato da mamo.
Ad esempio, ciò che tu hai fatto:
saClient.sin_addr=*((struct in_addr *)pHostinfo->h_addr);
è lecito, (ricordavo erroneamente che non si potesse fare un'assegnazione diretta tra struct). Quindi quel codice è ok.
Il problema risiede esclusivamente nel codice della RecvFrom che hai scritto. Infatti quella funzione ritorna solo nel caso di uno \n, che il client non manda mai. Ecco perchè con telnet funziona e con il client no... Prova ad esempio a commentare le due righe "do" e "while (...)", e vedrai che funziona.
Comunque puoi notevolmente migliorare tutto il codice ;)
Ah, quello che ho scritto prima è sempre valido, e ti permette di fare più controlli di errore sui dati passati (ma puoi farli anche sulla struct hosthent* tornata dalla gethostbyname() nello stesso modo in cui li ho fatti io, quindi scegli tu).
io nel codice postato sopra, per farlo andare, ho fatto solo quelle modifiche che ho scritto. In particolare send e recv e spostato il printf oltre alla porta.
sulla Client.sin_addr.. nessun problema visto che il "ciao!" arriva.
su 127.0.0.1 in locale funziona.
Forse intendi che con ip dinamico avrebbe dei problemi? invece che 127.0.0.1?
Mio refuso, ricordavo erroneamente che l'assegnazione diretta tra due struct non fosse lecita (per quanto con il metodo postato da me prima puoi fare un maggior controllo errori, ma si può fare anche diversamente controllando i valori nella struct hostent* tornata da gethostbyname). Comunque l'errore è nella RecvFrom, basta ad esempio commentare le 2 righe che ho indicato nel post precedente e tutto funziona.
eheh... ok problema risolto, grazie mille... :D
xò ce ne è un altro...
ho fatto una prova: ho solo aggiunto '\n' alla stringa ciao e quindi ora i segnali arrivano, solo che se chiudo il client il server non mi dice che è stato chiusa la connessione... mentre se chiudo telnet me lo dice... come mai?? :confused:
EDIT niente niente ho risolto :D
ora stavo provando a creare due funzioni, una nel client, l'altra nel serve per fare in modo che i due programmi si possano scambiare dei file... ma nn funzionano :mad: mi aiutate a capire xche?? grazie...
int invio_file(SOCKET sockinvio){
char thisbuffer[1000];
char nomefile[1000];
char nomefileclient[1000];
int nBytesP;
strcpy(thisbuffer,"");
strcat(thisbuffer,"nomefile:");
printf(thisbuffer);//richiesta di inserimento nome file
strcpy(thisbuffer,""); //cancelliamo buffer
strcpy(nomefile,"");
strcpy(nomefileclient,"");
gets(nomefile); //prendiamo nome del file
//riceviamo richiesta di invio nome destinazione
nBytesP = recv(sockinvio, thisbuffer, BUFFERSIZE, 0);
thisbuffer[nBytesP] = '\0';
printf(thisbuffer); //richiesta del nome del file da dare al client
gets(nomefileclient);
SendTo(sockinvio,nomefileclient);
//*** inizio invio file ***//
char filebuffer[10];
FILE *file = fopen(nomefile,"rb");
if (file==NULL) return 0;
fseek (file , 0 , SEEK_END);
long lSize = ftell (file);
rewind (file);
for(int x = 0; x < lSize ; x++) {
fread( filebuffer, 1, 1, file);
SendTo(sockinvio,filebuffer);
}
fclose(file);
#ifdef DEBUG_MODE
system("pause");
#endif
return 1;
}
void ricezione_file(SOCKET sockinvio){
int nBytesP;
char thisbuffer[1000];
char nomefile[1000];
strcpy(nomefile,"");
strcpy(thisbuffer,"");
strcat(thisbuffer,"url del file inviato:"); //invio richiesta nome file
SendTo(sockinvio,thisbuffer);
strcpy(thisbuffer,"");//cancellazione buffer
nBytesP = recv(sockinvio, nomefile, BUFFERSIZE, 0); //ricezione nome file
nomefile[nBytesP] = '\0';
#ifdef DEBUG_MODE
printf("nome file: %s",nomefile);
#endif
//*** inizio ricezione file ***//
char filebuffer[10];
FILE *file;
file = fopen (nomefile,"wb");
while(recv(sockinvio,filebuffer, 1, 0) != 0){ //scriviamo tutto il file...
filebuffer[1] = '\0';
fprintf(file,"%s",filebuffer);
}
fclose (file);
#ifdef DEBUG_MODE
system("pause");
#endif
}
ok problema risolto... grazie cmq :cool:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.