View Full Version : [C/C++] Guida socket
17Qwerty71
18-02-2006, 08:49
Avrei in progetto un programma che comunica tramite un'altro attraverso le socket, avete dei buoni tutorial (o guide) da propormi?
Premetto che sulle socket non conosco ancora nulla :stordita:
17Qwerty71
18-02-2006, 10:54
ma lavori su unix o win?
Win :stordita:
Fenomeno85
18-02-2006, 12:08
allora per windows esiste msdn ;) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/socket_2.asp
Non esiste nulla di + completo rispetto a msdn
~§~ Sempre E Solo Lei ~§~
allora per windows esiste msdn ;) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/socket_2.asp
Non esiste nulla di + completo rispetto a msdn
~§~ Sempre E Solo Lei ~§~
Per Win sicuramente, però nel caso dei socket mi pare opportuno prima uno studio sul meccanismo di comunicazione client-server (o p2p ma meglio lasciare p2p per dopo) ;)
17Qwerty71, a teoria dei socket come stai messo?
Mi quoto da solo...
17Qwerty71, a teoria dei socket come stai messo?
ho appena riletto il tuo primo messaggio. Vedo di cercarti qualche tutorial sul meccanismo dei socket sul web (altrimenti ti passo il materiale che ho ereditato dai corsi dell'università, ma meglio di no ;))
17Qwerty71
18-02-2006, 19:31
Mi quoto da solo...
ho appena riletto il tuo primo messaggio. Vedo di cercarti qualche tutorial sul meccanismo dei socket sul web (altrimenti ti passo il materiale che ho ereditato dai corsi dell'università, ma meglio di no ;))
Grazie, mi farebbe piacere dare uno sguardo alla teoria di comunicazione tra due dispositivi :)
Il programmino in questione comunica con un'altro tramite la rete lan, non so' se può tornare utile come informazione :stordita:
Uff sono di nuovo scomparsi i messaggi scritti in mattinata!! :incazzed:
Ti avevo messo due link, ora li devo cercare di nuovo... :grrr:
Grazie, mi farebbe piacere dare uno sguardo alla teoria di comunicazione tra due dispositivi :)
Il programmino in questione comunica con un'altro tramite la rete lan, non so' se può tornare utile come informazione :stordita: ah be', se lavori su una rete LAN allora puoi usare le named pipes oppure le mailslot che sono secondo me più semplici dei sockets; se invece pensi che in futuro dovrai far comunicare i tuoi programmi anche attraverso Internet allora è meglio che usi i sockets e che al momento opportuno ti studi le estensioni aggiunte da Microsoft nei Windows Sockets 2 per lavorare con protolli diversi.
EDIT: io una volta ho realizzato un programma per chattare su reti LAN che usava le mailslot; se vuoi ti passo i sorgenti (è fatto in Visual C++ 6 con MFC).
comunque ricordo che su alcune reti il programma aveva un problema che ritengo fosse dovuto a qualche malfunzionamento delle mailslots contro i quali ti devo avvisare: a volte (non so quando e non so perché) le mailslot riceventi ricevono gli stessi messaggi due o tre volte, sono abbastanza sicuro che non dipendesse dal mio programma (ho controllato molto approfonditamente con l'aiuto del debugger); mi era venuto in mente di risolvere la questione usando dei transaction IDs nei miei messaggi (il programma ricevente doveva ignorare messaggi con TrID uguale a quello di un messaggio precedente), ma alla fine non l'ho più fatto per pigrizia :p
attualmente il mio programma funziona alla perfezione tranne che su alcune reti i messaggi di chat arrivano 2 o raramente 3 volte :p
17Qwerty71
19-02-2006, 20:56
Uff sono di nuovo scomparsi i messaggi scritti in mattinata!! :incazzed:
Ti avevo messo due link, ora li devo cercare di nuovo... :grrr:
Mi farebbe piacere perchè mi sono scordato di salvare il link nei segnalibri :stordita:
ah be', se lavori su una rete LAN allora puoi usare le named pipes oppure le mailslot che sono secondo me più semplici dei sockets; se invece pensi che in futuro dovrai far comunicare i tuoi programmi anche attraverso Internet allora è meglio che usi i sockets e che al momento opportuno ti studi le estensioni aggiunte da Microsoft nei Windows Sockets 2 per lavorare con protolli diversi.
EDIT: io una volta ho realizzato un programma per chattare su reti LAN che usava le mailslot; se vuoi ti passo i sorgenti (è fatto in Visual C++ 6 con MFC).
comunque ricordo che su alcune reti il programma aveva un problema che ritengo fosse dovuto a qualche malfunzionamento delle mailslots contro i quali ti devo avvisare: a volte (non so quando e non so perché) le mailslot riceventi ricevono gli stessi messaggi due o tre volte, sono abbastanza sicuro che non dipendesse dal mio programma (ho controllato molto approfonditamente con l'aiuto del debugger); mi era venuto in mente di risolvere la questione usando dei transaction IDs nei miei messaggi (il programma ricevente doveva ignorare messaggi con TrID uguale a quello di un messaggio precedente), ma alla fine non l'ho più fatto per pigrizia
attualmente il mio programma funziona alla perfezione tranne che su alcune reti i messaggi di chat arrivano 2 o raramente 3 volte
Penso di rimanere con le WinSocks, perchè in un futuro penso di farlo comunicare attraverso internet :)
Ho ritrovato i link nella cronologia per fortuna...
A questo (http://unsecure.altervista.org/socket/socket.htm) indirizzo puoi trovare una breve ma efficace guida sulla programmazione con winsock (si riferisce alla 1.1 ma per cominciare va benissimo, nulla di diverso dalla 2.0), presenta degli esempi di codice carini e commentati, ed è in italiano. La guida non si sofferma su problematiche pù avanzate come socket bloccanti/non bloccanti, broadcast/multicast ecc., ma appunto va bene per cominciare e fare subito qualche programma interessante. La guida è in italiano.
A quest'altro (http://www.exegesis.uklinux.net/gandalf/winsock/) indirizzo trovi invece una guida un po' più approfondita della precedente, ma in inglese. Ah, ho letto velocemente la prima metà e ti consiglio di saltare la parte sulla configurazione del compilatore, è inutile se usi un compilatore Microsoft (VisualStudio - è tutto già configurato) ma anche in altri IDE (tipo Borland) di solito è già tutto a posto.
Un'ultima cosa: nella prima guida, ho dato un'occhiata al programma di esempio "bannerscan.c" in cui prova ad usare un socket non bloccante. Puoi leggerlo se vuoi, ma non prenderlo ad esempio ;) Il modello non bloccante è più complesso di quello brevemente presentato in quell'esempio: lì praticamente, invece di aspettare la risposta del server per un tempo illimitato (modello bloccante) attende la risposta per un tempo prefissato, e se non c'è risposta passa al server successivo (!!). Questo è un comportamento assolutamente da evitare, perchè poco efficiente e porta quasi sempre a perdita di informazioni in una rete non LAN (ma anche in LAN molot "cariche"). Il modello non bloccante è invece "asincorno", e permette di ricontattare il server che in un primo momento non aveva risposto quando lo stesso server comunica che vuole mandare i dati richiesti. Per il resto tutto ok (ma del resto per cominciare il modello non bloccante lascialo perdere).
Ciao :)
ah be', se lavori su una rete LAN allora puoi usare le named pipes oppure le mailslot che sono secondo me più semplici dei sockets; --cut--
Il meccanismo mailslot è molto semplice ed efficace se si lavora in rete locale (se non erro infatti non è possibile usare il meccanismo mailslot tra pc che risiedono in ip-range differenti), offre il meccanismo broadcast in modo trasparente, ma presenta una grande pecca.
Per comunicare, il meccanismo mailslot utilizza messaggi datagram (UDP) che non garantiscono alcun controllo sull'effettiva ricezione del messaggio. Se da un lato sono asincroni, e quindi evitano al programmatore i vari controlli sull'invio dei messaggi, dall'altro non puoi sapere se il messaggio inviato è stato effettivamente ricevuto oppure no. Quando si lavora con una mole di dati più consistente, diventa davvero inopportuno rischiare che il dato non arrivi a destinazione. Un'altra pecca è che i mailslot non sono portabili (sono supportati solo da sistemi Windows) a differenza dei sockets.
Il meccanismo mailslot è molto semplice ed efficace se si lavora in rete locale (se non erro infatti non è possibile usare il meccanismo mailslot tra pc che risiedono in ip-range differenti), offre il meccanismo broadcast in modo trasparente, ma presenta una grande pecca.
Per comunicare, il meccanismo mailslot utilizza messaggi datagram (UDP) che non garantiscono alcun controllo sull'effettiva ricezione del messaggio. Se da un lato sono asincroni, e quindi evitano al programmatore i vari controlli sull'invio dei messaggi, dall'altro non puoi sapere se il messaggio inviato è stato effettivamente ricevuto oppure no. Quando si lavora con una mole di dati più consistente, diventa davvero inopportuno rischiare che il dato non arrivi a destinazione. Un'altra pecca è che i mailslot non sono portabili (sono supportati solo da sistemi Windows) a differenza dei sockets.be', anche per quelli c'è qualche differenza, bisogna stare attenti ai valori di ritorno, perciò alla fine qualche #ifdef a sporcare il codice ci va lo stesso.
per quanto riguarda le mailslot è vero che sono basate su un protocollo inaffidabile ma non concordo con il discorso sul lavorare con una grande mole di dati. una volta che il programmatore è "aware" del fatto che il protocollo sottostante è inaffidabile, il meccanismo di per se' rimane comunque più semplice da gestire rispetto a qualsiasi altro meccanismo sincrono: il fatto che io debba inviare dati da molti punti del codice non significa che per ciascuno di quei punti io debba fare altrettanti controlli circa l'arrivo o meno del messaggio; il controllo lo faccio una volta sola per tutte in una funzione apposita, e solo se serve perché in realtà considerando che il programmatore è cosciente di basarsi su un protocollo inaffidabile, progetterà la sua architettura di conseguenza, cioè senza mai fare in modo che tra una ricezione e l'altra i dati assumano uno stato incosistente. ovviamente il programmatore deve sempre valutare se nel suo caso sia realmente opportuno basarsi su un protocollo inaffidabile.
e poi via, se la rete è in buone condizioni fisiche quante volte le mailslot falliranno? anzi, a me pare che spesso funzionino bene il doppio o il triplo di come dovrebbero... :p
per quanto riguarda le mailslot è vero che sono basate su un protocollo inaffidabile ma non concordo con il discorso sul lavorare con una grande mole di dati. una volta che il programmatore è "aware" del fatto che il protocollo sottostante è inaffidabile, il meccanismo di per se' rimane comunque più semplice da gestire rispetto a qualsiasi altro meccanismo sincrono: il fatto che io debba inviare dati da molti punti del codice non significa che per ciascuno di quei punti io debba fare altrettanti controlli circa l'arrivo o meno del messaggio; il controllo lo faccio una volta sola per tutte in una funzione apposita, e solo se serve perché in realtà considerando che il programmatore è cosciente di basarsi su un protocollo inaffidabile, progetterà la sua architettura di conseguenza, cioè senza mai fare in modo che tra una ricezione e l'altra i dati assumano uno stato incosistente. ovviamente il programmatore deve sempre valutare se nel suo caso sia realmente opportuno basarsi su un protocollo inaffidabile.
e poi via, se la rete è in buone condizioni fisiche quante volte le mailslot falliranno? anzi, a me pare che spesso funzionino bene il doppio o il triplo di come dovrebbero... :p
Sicuramente usare i mailslots è molto più semplice che usare i socket, per quanto le sue potenzialità siano limitate.
Comunque non ho capito una cosa del tuo ragionamento. Giacchè i mailslots usano un protocollo di trasporto inaffidabile, si pone il seguente problema:
1) un mailslot client invia un messaggio ad un mailslot server (magari in broadcast)
2) i mailslot server, controllando la coda messaggi, NON possono sapere se qualche messaggio è stato inviato (se trovano la coda vuota).
Tu mi dici che il programmatore, sapendo questo, organizza l'architettura di invio/ricezione in modo più intelligente. Ok, mi viene in mente ad esempio di fare una sorta di handshaking tra mailslot client e server per minimizzare il rischio di perdita messaggi. In questo caso però il numero di messaggi da scambiare tra client e server per singola transazione aumenta, peggiorando le prestazioni.
Il discorso nasce dal fatto che dici
"il fatto che io debba inviare dati da molti punti del codice non significa che per ciascuno di quei punti io debba fare altrettanti controlli circa l'arrivo o meno del messaggio; il controllo lo faccio una volta sola per tutte in una funzione apposita"
Come fai a controllare se il messaggio è arrivato? Devi implementare comunque un'architettura più sicura credo (tipo handshake).
EDIT: dimenticavo, i socket non sono necessariamente sincroni ;) ok quelli asincroni sono più diffci da implementare, ma offrono grandi potenzialità e prestazioni. Questo a prescindere dai mailslot: mi sembra giusto, se devo implementare un semplice programma di IPC in LAN, usare un meccanismo più semplice dei socket: inutile sparare al passerotto col bazooka :D
17Qwerty71
23-02-2006, 21:52
WSADATA data; // inizializzo la variabile che contiene le primitive di Winsock
WORD Version;
int err=0; // inizializzo una variabile per gestire gli errori
Version=MAKEWORD(2,0); // creo la variabile p che contiene la versione della wsock32.dll
err=WSAStartup(Version,&data); // inizializzo la wsock32.dll verificandone la mancanza di errori
SOCKET sock=socket(PF_INET,SOCK_STREAM,0);
sockaddr_in sock_addr;
sock_addr.sin_family=PF_INET; // indico il protocollo utilizzato (TCP/IP)
sock_addr.sin_port=htons(21); //indico la porta a cui connettere il socket
sock_addr.sin_addr.S_un.S_un_b.s_b1=127; // indico l'indirizzo IP
sock_addr.sin_addr.S_un.S_un_b.s_b2=0;
sock_addr.sin_addr.S_un.S_un_b.s_b3=0;
sock_addr.sin_addr.S_un.S_un_b.s_b4=1;
err=connect(sock,(struct sockaddr*)&sock_addr,sizeof(struct sockaddr));
closesocket(sock);
WSACleanup();
Il compilatore non mi riconosce la struttura sockaddr_in (ho include winsock.h) :muro:
Fenomeno85
24-02-2006, 07:58
WSADATA data; // inizializzo la variabile che contiene le primitive di Winsock
WORD Version;
int err=0; // inizializzo una variabile per gestire gli errori
Version=MAKEWORD(2,0); // creo la variabile p che contiene la versione della wsock32.dll
err=WSAStartup(Version,&data); // inizializzo la wsock32.dll verificandone la mancanza di errori
SOCKET sock=socket(PF_INET,SOCK_STREAM,0);
sockaddr_in sock_addr;
sock_addr.sin_family=PF_INET; // indico il protocollo utilizzato (TCP/IP)
sock_addr.sin_port=htons(21); //indico la porta a cui connettere il socket
sock_addr.sin_addr.S_un.S_un_b.s_b1=127; // indico l'indirizzo IP
sock_addr.sin_addr.S_un.S_un_b.s_b2=0;
sock_addr.sin_addr.S_un.S_un_b.s_b3=0;
sock_addr.sin_addr.S_un.S_un_b.s_b4=1;
err=connect(sock,(struct sockaddr*)&sock_addr,sizeof(struct sockaddr));
closesocket(sock);
WSACleanup();
Il compilatore non mi riconosce la struttura sockaddr_in (ho include winsock.h) :muro:
devi linkare wsdata.lib o qualcosa del genere ;)
comunque l'ip non si mette in quel modo ;)
~§~ Sempre E Solo Lei ~§~
@ 17Qwerty71
Sì, devi indicare al compilatore che vuoi usare la libreria winsock2.dll.
Per farlo, ad esempio con visual studio, basta andare nelle opzione del progetto e, nella sezione (se non sbaglio) link (dai un'occhiata...), devi dire di includere lo stub 'winsock2.lib'. Lo stub .lib è uno speciale file include che informa il compilatore di linkare vs winsock2.dll
e io che ho letto la guida e non ho idea di che farci con sti socket?? sono stupido? cioe, vorrei fare qualcosa di semplice per vedere se ho capito, ma non so nemmeno da dove partire...mi fa piacere che mi venga spiegato come si programmano i socket, ma alla fine di quella guida minuscola e e sicuramente non esaustiva c e una perla: "ora che sappiamo programmare i socket, possiamo fare fakemailers, trojan, eccetera"...sono sempre piu convinto di non avere alcuna dote naturale per la programmazione, perche io dopo aver letto quella guida, ne so sui socket quanto ne sapevo prima, cioe nulla; non so perche funzionano, non so cosa sono, non so come utilizzarli...so solo a grandi linee cosa fanno e come si devono utilizzare...possibile che ci esistano cervelloni che dopo aver letto una guida simile, a digiuno completo di socket, possano scrivere un programma qualsiasi che compila ed esegue qualcosa? non so tipo far venire fuori un messaggio "ciao!" in un computer in lan o sul proprio schermo? bah, ho sbagliato universita, me ne convinco sempre di piu ormai :(
e io che ho letto la guida e non ho idea di che farci con sti socket?? sono stupido? cioe, vorrei fare qualcosa di semplice per vedere se ho capito, ma non so nemmeno da dove partire...mi fa piacere che mi venga spiegato come si programmano i socket, ma alla fine di quella guida minuscola e e sicuramente non esaustiva c e una perla: "ora che sappiamo programmare i socket, possiamo fare fakemailers, trojan, eccetera"...sono sempre piu convinto di non avere alcuna dote naturale per la programmazione, perche io dopo aver letto quella guida, ne so sui socket quanto ne sapevo prima, cioe nulla; non so perche funzionano, non so cosa sono, non so come utilizzarli...so solo a grandi linee cosa fanno e come si devono utilizzare...possibile che ci esistano cervelloni che dopo aver letto una guida simile, a digiuno completo di socket, possano scrivere un programma qualsiasi che compila ed esegue qualcosa? non so tipo far venire fuori un messaggio "ciao!" in un computer in lan o sul proprio schermo? bah, ho sbagliato universita, me ne convinco sempre di piu ormai :(
Beh la prima guida che ho postato non è definibile come guida esaustiva... Magari la seconda è più completa (ma in inglese).
Cmq per programmare i socket ci vuole come prerequisito una sufficiente conoscenza della programmazione C.
Cos'è che non ti è chiaro?
mi sono espresso malissimo perche ero amareggiato...il mio problema non è tanto il non avere capito un h, che è risolvibile...il mio problema è che non ho in alcun modo l acume per articolare un ragionamento su quello che ho letto...non ho assolutamente idea di come produrre qualcosa che funzioni (anche qualcosa di basilare, come un esempio di stampa di "ciao"), mentre da quello che mi sembra di capire, dovrei eccome...la base in c ce l ho, altrimenti non avrei nemmeno guardato il 3d (certo in java me la cavo di piu, ma non mi spaventa guardare 2 righe di c)
ad esempio: i due stralci server.c e client.c che ci sono in quella guida...che fanno? ho provato a pastarli in codeblocks e ed eseguirli ma non succede nulla...la cosa piu deprimente è che parlo come un niubbo totale ("ho provato ad eseguirli ma non succede nulla", odioso...) quando non lo sono, o non dovrei esserlo giacche sono ormai 3 anni che me la sbuccio con la programmazione all uni...a volte ci provo a pensare di non essere inutile, ma non c e verso, non c e una sola cosa che padroneggi bene, non mi stupirei di sbagliare un algoritmo elementare sugli array a questo punto...
lol è incredibile...sto leggendo anche il tutorial in eng...ho rinunciato a capire il whois.c circa a meta (mi sono perso)...alla fine, dopo le dovute premesse dell autore (che addirittura ha detto che chi non avesse mai visto c poteva consultare una guida per capire "di cosa si trattasse"), ha detto: "beh nulla di difficile finora"....è questo che intendo...mi infastidisce la mia persona, il mio cervello inutilmente goffo...caz se qualcuno ci arriva, vuol dire che si puo...la costante della mia vita è invece che capisco sempre le cose a posteriori e in maniera precaria...ma baffangulo a me stesso va...
ad esempio: i due stralci server.c e client.c che ci sono in quella guida...che fanno? ho provato a pastarli in codeblocks e ed eseguirli ma non succede nulla...la cosa piu deprimente è che parlo come un niubbo totale ("ho provato ad eseguirli ma non succede nulla", odioso...) quando non lo sono, o non dovrei esserlo giacche sono ormai 3 anni che me la sbuccio con la programmazione all uni...a volte ci provo a pensare di non essere inutile, ma non c e verso, non c e una sola cosa che padroneggi bene, non mi stupirei di sbagliare un algoritmo elementare sugli array a questo punto...
E molto semplice: sono due programmi separati, il client ed il server. In un modello client-server, c'è chi ascolta le richieste ed esegue delle operazioni corrispondenti alla richiesta (il server) e chi effettua le richieste (il client). Immagina il meccanismo browser (client)-sito internet (server): il browser si connette ad un sito e richiede una pagina: il sito ascolta la richiesta e manda la pagina richiesta al browser.
Queste cose penso le sai già, ma era per introdurre.
Un socket è un modo per creare un collegamento tra due programmi: immaginalo come un tubo che trasferisce informazioni. il tubo ovviamente ha due estremità: una collegata al programma che chiede, l'altra collegata a chi ascolta. E' necessario specificare per le due estremità DOVE devono essere collegate.
Ora, tu fai due programmi separati: server.c e client.c.
server.c fa questo: crea una delle due estremità del tubo (il socket di ascolto). Il socket di ascolto, per essere raggiungibile dall'esterno, deve essere collegato all'indirizzo ip del pc su cui il server gira: in più giacchè possono esserci altri socket in ascolto su quell'ip, si deve specificare una porta di ingresso per quell'ip. Ogni ip puo' avere 2^16 porte: si sceglie una porta libera e non riservata, e spesso il numero della è internazionalmente riconosciuto da altri programmi per un servizio preciso. Ad esempio, la porta per le connessioni HTTP è 80. Per un tuo programma privato, usa una porta a caso dal numero alto, ad esempio 8100.
Ricapitolando, il server crea un socket, lo lega (bind) ad un indirizzo ip ed ad una porta, e si mette in ascolto (listen).
client.c fa questo: crea l'altra estremità del tubo (il socket di richiesta). ma non si mette in ascolto (facendo il bind su un ip-porta). Dopo la creazione del socket, semplicemente specifica un ip ed una porta a cui vuole parlare e si connette: se l'ip e la porta specificata esiste, il tubo viene creato.
Una volta creato il tubo, il client scrive dei dati sul socket: questo dati vengono automaticamente recapitati al server, che viene avvisato quando dei dati arrivano: in più, all'arrivo dei dati, il socket del server indica DA CHI i dati sono arrivati (non può saperlo a priori, dal momento che tutti possono collegarsi). Per semplicità, il server (in automatico) sdoppia il socket di ascolto e lo collega stabilmente col socket di richiesta, così da gestire facilmente il dialogo. Il socket iniziale (che non a caso viene chiamato master socket) rimane cos' liber e pronto per altre richieste (che possono giungere mentre il server gestisce i dati). Arrivati i dati, il server li legge, li elabora, ed in base ai dati arrivati si comporta di conseguenza: scrive dei dati sul suo socket (quello sdoppiato per gestire la connessione). Appena scritti, il suo socket li manda al client, che li legge e li gestisce.
Faccio un esempio banale:
Il server crea il socket di ascolto, lo lega all ip-porta della macchina su cui viene eseguito e si mette in ascolto.
Un client crea un socket e si collega al server. Una volta connesso, scrive sul socket la stringa "Ciao, come stai?".
Il server riceve la stringa, sdoppia il suo master socket per gestire la connessione e legge su quest'ultimo socket i dati inviati. Legge "Ciao, come stai?"
Il server è stato programmato per riconoscere una richiesta del genere. Quindi risponde, scrivendo sul suo socket sdoppiato la stringa "Tutto bene, grazie!".
Questa stringa viene recapitata al client, che la legge e ad esempio la visualizza.
Se il server non riconosce la stringa (perchè il programmatore del server implementa solo un set limitato di possibili richieste), mandaper esempio la stringa "Che volevi dire?": il client la riceve, vede che il server non ha capito e stampa ad esempio "Il server non ha capito...".
Questo è il concetto: ovviamente le problematiche sono innumerevoli: ad esempio, se il server riceve una seconda richiesta da un altro client mentre sta elaborando un'altra richiesta, che si fa? O meglio, come fa?, dal momento che i linguaggi di programmazione sono procedurali. Il server in questo caso deve essere multiprocesso (o multithread in Windows), in cui ogni processo/thread gestisce autonomamente una connessione, ma la cosa si complica ed esula dalla semplice spiegazione di prima.
sei gentilissimo e ti ringrazio per il tempo che mi hai dedicato...il mio problema è pero sempre lo stesso; queste cose sono abbastanza facili da interiorizzare, insomma è il meccanismo client server...so cosa fa, ma non so come farglielo fare...una guida che spiega il cosa ma non il come non mi fara mai arrivare a un codice eseguibile, un esempio tangibile, almeno parlo per il mio cervello ristretto...server.c e client.c (in quel tutorial in italiano) che cosa fanno? so a cosa servono, ma se io volessi un programma che se io scrivo in console "come va?" lui mi risponda "bene grazie", quei due file come potrebbero servirmi? cioe basta mdificarli un po, ma è quel po che io non riesco a raggiungere intellegibilmente..alla fine sara una domanda banalissima e da newby, il fatto è che non avendolo mai visto me lo potro immaginare molto difficilmente (imho), mentre in qualsiasi tutorial ti spiegano "questi sono i metodi e funziona cosi" [...] "ora che sappiamo questo possiamo scrivere un p2p"....ovviamente è un esempio esagerato, ma è cosi che lo vedo...non sto parlando solo di questo caso, mi sembra che sia una costante della mia vita: qualsiasi cosa in cui mi infogno sono punto e daccapo, sembra che non ci arrivi alle cose, oppure su internet ci sono solo geni che gli dai il la eti scrivono mezza pagina di codice senza nemmeno pensare....sta cosa è frustrantissima perche son 3 mesi che dico "devo imparare a sockettare visto che l anno prossimo ho prog in rete e tanto mi tocchera", ma mi fermo sempre a uno scoglio qualsiasi....ora che ci ero vicino a infognarmi, capisco che manco con un esempio completo e funzionante riesco a raccapezzarmi...e non è perche mi manchi la logica di come funziona un client server (ripeto, sembra abb basilare e ovvio quello), ma perche non so come scrivere e dove scrivere quello che mi interessa...boh lassiamo perdere va che tanto sono una causa persa...
17Qwerty71
24-02-2006, 13:41
@ 17Qwerty71
Sì, devi indicare al compilatore che vuoi usare la libreria winsock2.dll.
Per farlo, ad esempio con visual studio, basta andare nelle opzione del progetto e, nella sezione (se non sbaglio) link (dai un'occhiata...), devi dire di includere lo stub 'winsock2.lib'. Lo stub .lib è uno speciale file include che informa il compilatore di linkare vs winsock2.dll
Scusa, ma dove trovo questa libreria? :confused:
Uso CodeBlocks :)
sei gentilissimo e ti ringrazio per il tempo che mi hai dedicato...il mio problema è pero sempre lo stesso; queste cose sono abbastanza facili da interiorizzare, insomma è il meccanismo client server...so cosa fa, ma non so come farglielo fare...una guida che spiega il cosa ma non il come non mi fara mai arrivare a un codice eseguibile, un esempio tangibile, almeno parlo per il mio cervello ristretto...server.c e client.c (in quel tutorial in italiano) che cosa fanno? so a cosa servono, ma se io volessi un programma che se io scrivo in console "come va?" lui mi risponda "bene grazie", quei due file come potrebbero servirmi? cioe basta mdificarli un po, ma è quel po che io non riesco a raggiungere intellegibilmente..alla fine sara una domanda banalissima e da newby, il fatto è che non avendolo mai visto me lo potro immaginare molto difficilmente (imho), mentre in qualsiasi tutorial ti spiegano "questi sono i metodi e funziona cosi" [...] "ora che sappiamo questo possiamo scrivere un p2p"....ovviamente è un esempio esagerato, ma è cosi che lo vedo...non sto parlando solo di questo caso, mi sembra che sia una costante della mia vita: qualsiasi cosa in cui mi infogno sono punto e daccapo, sembra che non ci arrivi alle cose, oppure su internet ci sono solo geni che gli dai il la eti scrivono mezza pagina di codice senza nemmeno pensare....sta cosa è frustrantissima perche son 3 mesi che dico "devo imparare a sockettare visto che l anno prossimo ho prog in rete e tanto mi tocchera", ma mi fermo sempre a uno scoglio qualsiasi....ora che ci ero vicino a infognarmi, capisco che manco con un esempio completo e funzionante riesco a raccapezzarmi...e non è perche mi manchi la logica di come funziona un client server (ripeto, sembra abb basilare e ovvio quello), ma perche non so come scrivere e dove scrivere quello che mi interessa...boh lassiamo perdere va che tanto sono una causa persa...
Nessun problema, quando ho un po' di tempo lo dedico volentieri.
L'importante in una connessione client-server è stabilire la connessione. I tutorial normalmente spiegano proprio questo.
Una volta stabilita la connessione, è importante sapere come inviare i dati: i tutorial spiegano anche questo: semplicemente si usano le funzioni read() e write() sui socket, proprio come fossero dei file aperti con fopen.
Tutto il resto spetta a te programmatore. Il dialogo client-server viene implementato programmando il cosiddetto protocollo a livello applicativo. Ce ne sono di ben definiti (come l'HTTP).
Semplicemente il server deve saper riconoscere un numero X di comandi, e reagire di conseguenza.
Esempio:
- Il server riconosce i comandi "CHE_ORE_SONO" e "CHE_GIORNO_E": se il comando non è riconosciuto invia un messaggio di errore.
- il client manda al server la stringa "CHE_ORE_SONO".
- il server legge la stringa: se è uguale ad uno dei comandi conosciuti, esegue la funzione associata. Il server riconosce i comandi ad esempio con un costrutto case, nulla di complicato. Nel nostro esempio, il server legge l'ora del sistema su cui è in esecuzione e la scrive sul socket per inviarla al client richiedente.
- il client legge la risposta: se non è un messaggio di errore, prende la risposta e la elabora secondo i suoi comodi. Se è un messaggio di errore, si comporta di conseguenza.
L'importante è imparare come scrivere su e leggere da un socket (facile) e soprattutto attendere che (nel caso della lettura) ci siano dei dati nel socket. Imparare a sincronizzare il tutto insomma.
L'elaborazione dei comandi sta alla tua fantasia: o ti inventi un semplice protocollo di comunicazione (implementi insomma le parole conosciute dal client e dal server) oppure usi un protocollo esistente (sconsigliato per le prime prove...).
Esistono dei protocolli internazionalmente conosciuti ai programmatori (come l'HTTP) proprio perchè sennò la comunicazione tra client e server sarebbe impossibile. Il client DEVE sapere quali comandi sono riconosciuti dal server, COME il server manda le risposte e COME il server si comporta in caso di errore.
EDIT: appena ho tempo nel pomeriggio, prendo quei 2 esempi del tutorial italiano e li modifico in modo tale da implementare l'esempio che ho fatto rpima con CHE_ORE_SONO, così ti fai un'idea precisa. Appena posso riavviare il pc ed andare in Windows lo faccio ;)
EDIT 2: Anzi, se non mi sbaglio conservo ancora un esempio client server fatto come uno dei primi esercizi ai tempi dell'università, tutto commentato e per windows.
Vado a controllare.
EDIT 3: Uff sono già tutti a finestre, quindi c'è tutto il message loop di windows che non ti interessa in questo caso e ti incasinerebbe ancora di più. Te lo faccio da 0.
Scusa, ma dove trovo questa libreria? :confused:
Uso CodeBlocks :)
Ah... Viene fornita con la SDK di visual studio. ti serve lo stub per usare la libreria facendo semplicemente #include <winsock.h>, altrimenti devi caricare la libreria in modo dinamico...
Se non hai visual studio, vai sul sito Microsoft e scarica l'SDK API di Windows, è gratuita.
Ma cmq dovrebbe già esserci su pc, ma non ne sono sicuro a dire il vero. Fai appunto un giro sul sito MS o con google.
17Qwerty71
24-02-2006, 21:58
Ah... Viene fornita con la SDK di visual studio. ti serve lo stub per usare la libreria facendo semplicemente #include <winsock.h>, altrimenti devi caricare la libreria in modo dinamico...
Se non hai visual studio, vai sul sito Microsoft e scarica l'SDK API di Windows, è gratuita.
Ma cmq dovrebbe già esserci su pc, ma non ne sono sicuro a dire il vero. Fai appunto un giro sul sito MS o con google.
Sul pc tengo già installato il Platform SDK, ma nemmeno li si trova :(
Ho cercato anche tra le cartelle del VC che tengo installato ma nulla
Ho fatto pure la ricerca completa in tutto il C e ovviamente non mi ha trovato niente :muro:
Sono costretto ad utilizzare CodeBlocks perchè VC non dispone di un'editor di .rc e poi nn mi ci trovo con quel compilatore :cry:
Su google di quella libreria non trovo risultati in ita e nel resto delle lingue non trovo roba interessante :confused:
Ho provato anche ad includere la libreria libws2_32.a appartenente alla raccolta delle librerie del Dev, ma niente :(
Vi prego, ho urgente bisogno di fare un progetto con le socket :cry:
Sul pc tengo già installato il Platform SDK, ma nemmeno li si trova :(
Ho cercato anche tra le cartelle del VC che tengo installato ma nulla
Ho fatto pure la ricerca completa in tutto il C e ovviamente non mi ha trovato niente :muro:
Sono costretto ad utilizzare CodeBlocks perchè VC non dispone di un'editor di .rc e poi nn mi ci trovo con quel compilatore :cry:
Su google di quella libreria non trovo risultati in ita e nel resto delle lingue non trovo roba interessante :confused:
Ho provato anche ad includere la libreria libws2_32.a appartenente alla raccolta delle librerie del Dev, ma niente :(
Vi prego, ho urgente bisogno di fare un progetto con le socket :cry:
Fai una ricerca nel tuo pc con il trova di Windows ;) Cerca il seguente file:
ws2_32.lib
appena lo trovi, segnati la cartella in cui è contenuto e la dai in pasto al linker. Ah, c'è un metodo (che con il compilatore Microsoft funziona) per specificare gli stub .lib da usare direttamente all'interno del codice. Si usa la direttiva #pragma. Per farti un'idea, puoi guardare gli esempi di client e server che sto per postare ;)
@dnarod, ma anche a tutti quelli a cui interessa :D
Posto qui un semplice ma didattico esempio di un programma client-server.
Ho riscritto sia il client che il server da zero, quelli fatti nel tutorial erano un po' bizzarri su alcune scelte (tipo assegnare l'ip alla struct sockaddr in quel modo...).
Ho scritto il codice completamente in plain C ed è tutto commentato (ho perso più tempo a commentare che a scrivere il codice ;)
Sono 2 files .zip, uno contiene il client, l'altro il server. Per semplicità, includo anche i file di progetto di visual studio (ho usato .NET): se avete VS .NET cliccate semplicemente sul file .sln per ogni progetto per aprirlo.
Comunque, entrambi i programmi sono composti di un unico file .c ...
Ah, ho inserito anche gli eseguibili: potete provarli subito quindi.
Basta aprire due prompt dei comandi MS-DOS: in uno digitate
simpleserver 8001
nell'altro digitate
simpleclient 127.0.0.1 8001
in alternativa scrivete solo il nome dell'eseguibile per avere un breve help.
Buon divertimento, e spero che vi sia utile ;)
EDIT: Per il client, ho dovuto mettere l'eseguibile in un file zip separato, altrimenti il forum non me li faceva allegare (per le dimensioni per lui eccessive...).
EDIT 2: Dimenticavo, potete provare anche ad usare più client collegati ad un solo server. Basta aprire più prompt di MS-DOS (uno per ogni client) e lanciarli. Potete provare a lanciare i client su pc diversi anche (ovviamente)...
Con più client sullo stesso server, potrete anche vedere i problemi che un server bloccante monoprocesso comporta.
io sonon partito da questi esempi
http://unsecure.altervista.org/socket/socket.htm
io sonon partito da questi esempi
http://unsecure.altervista.org/socket/socket.htm
Prova a guardare il codice dei programmi che ho postato ieri e ad eseguirli, sono completamente commentati.
Ho notato che su quel tutorial ci sono delle cose strane, come ad esempio:
sock_addr.sin_addr.S_un.S_un_b.s_b1=127; // indico l'indirizzo IP
sock_addr.sin_addr.S_un.S_un_b.s_b2=0;
sock_addr.sin_addr.S_un.S_un_b.s_b3=0;
sock_addr.sin_addr.S_un.S_un_b.s_b4=1;
Si può fare (ed è consuetudine) fare più semplicemente così:
sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
uso anch'io quella forma nel mio codice :)
ne approfitto per chiederti: secondo te, quale di queste due assegnamenti sotto non funziona, e perchè ?
miosock_addr.sin_port=htons(80);
miosock_addr.sin_port=htons(atoi(argv[1]));
Stamattina ho leggermente modificato il codice di SimpleClient.c per renderlo più snello. Inizializzo la struttura struct sockaddr_in del socket client una volta per tutte, invece di farlo prima di ogni connect.
Avevo fatto quella scelta per rendere più chiari i passi da compiere per connettersi ad un server, però ho reputato che fosse un esempio di programmazione non buona (c'era troppo overhead).
uso anch'io quella forma nel mio codice :)
ne approfitto per chiederti: secondo te, quale di queste due assegnamenti sotto non funziona, e perchè ?
miosock_addr.sin_port=htons(80);
miosock_addr.sin_port=htons(atoi(argv[1]));
vanno bene entrambe, a patto che il primo parametro passato a riga di comando dal programma sia un numero.
Se l'argomento della atoi() non è un numero o è un numero troppo grande, il valore di ritorno non è definito (al meglio restituisce 0). Non ti dà errore, ma la porta poi è sballata.
Prova: assegna alla atoi una stringa, e poi leggi il valore assunto da miosock_addr.sin_port in questo modo:
unsigned short int port = ntohs(miosock_addr.sin_port);
vanno bene entrambe, a patto che il primo parametro passato a riga di comando dal programma sia un numero.
Se l'argomento della atoi() non è un numero o è un numero troppo grande, il valore di ritorno non è definito (al meglio restituisce 0). Non ti dà errore, ma la porta poi è sballata.
Prova: assegna alla atoi una stringa, e poi leggi il valore assunto da miosock_addr.sin_port in questo modo:
unsigned short int port = ntohs(miosock_addr.sin_port);
stranamente a me con la seconda forma .......argv[1]......non funziona all'attao della esecuzione.
Il primo assegnamento mette in ascolto in modo corretto il server sulla porta 80, il secondo invece, su una porta indefinita.
Non ho ancora svelato il mistero, boh :D
stranamente a me con la seconda forma .......argv[1]......non funziona all'attao della esecuzione.
Il primo assegnamento mette in ascolto in modo corretto il server sulla porta 80, il secondo invece, su una porta indefinita.
Non ho ancora svelato il mistero, boh :D
Se stai provando il secondo metodo in modalità debugger del development IDE, assicurati di indicare al debugger che vuoi passare un parametro al programma e quale parametro vuoi passare ;)
EDIT: il secondo metodo l'ho usato nel mio programma di esempio SimpleServer.c postato prima. Se vuoi dacci un'occhiata ;)
fidel sei un grande...grazie per i tips e per il lavorone che hai fatto! ho gia capito di piu su sti socket (anche se a dire la verita con java me la sono cavata al primo tentativo) ma non so come mai i prog che hai linkato non mi funzioano....forse sbaglio io?? li compilo e li eseguo ma non fanno nulla...sara che devo settare il compilatore in qualche modo (uso codeblocks che preferisco a devcpp) come dice nelle guide?
fidel sei un grande...grazie per i tips e per il lavorone che hai fatto! ho gia capito di piu su sti socket (anche se a dire la verita con java me la sono cavata al primo tentativo) ma non so come mai i prog che hai linkato non mi funzioano....forse sbaglio io?? li compilo e li eseguo ma non fanno nulla...sara che devo settare il compilatore in qualche modo (uso codeblocks che preferisco a devcpp) come dice nelle guide?
Grazie per la stima :)
Se hai problemi di compilazione con Codeblocks, ho incluso gli eseguibili dei due programmi, così puoi provarli. Devi lanciarli a riga di comando (in due Prompt di MS-DOS separati come spiegato prima.) Se li lanci col doppio click esce subito perchè vuole dei parametri passati a riga di comando (e col doppio click non passi nulla), e WinXP di default chiude la finestra MS-DOS al termine dell'applicazione ;)
Cmq non ho capito bene, con Codeblocks compila ed esegue? Se è così, e vuoi lanciare il programma da codeblocks, devi dire al debugger di passare gli argomenti a riga di comando, altrimenti si ripete il discorso fatto prima sul doppio click. Vai nelle opzioni progetto di Codeblocks, cerca le opzioni del debugger e cerca un'opzione che parla di "command line argument": lì ci scrivi gli argomenti da passare.
Sennò è come se lanci il programma senza parametri (dal prompt MS-DOS è come se scrivessi solo il nome del programma: prova con il prompt (lo trovi nel menu' Start->Accessori') e vedi cosa succede a lanciare i due programmi senza argomenti :)
Scrivo un piccolo promemoria delle operazioni effettuate dal client e dal server sui socket per abilitare la connessione, penso possa tornare utile (ed è questo lo schema che ho seguito nei due programmi allegati prima):
il server:
1) crea il master socket (quello che ascolta per le connessioni in arrivo)
2) definisce l'indirizzo e la porta su cui si metterà in ascolto (nel programma allegato, per l'indirizzo del server, uso l'indirizzo speciale INADDR_ANY: in questo modo il programma legge automaticamente l'indirizzo ip della macchina su cui il programma stesso è in esecuzione, senza così doverlo specificare manualmente come parametro)
3) lega (bind) l'indirizzo-porta specificati al master socket
4) si mette in ascolto
5) all'arrivo di una richiesta di connessione, la accetta. Quando la accetta, la funzione 'accept()' restituisce in caso di succeso un nuovo socket, che serve a gestire la connessione con il client: in questo modo il master socket rimane libero per l'ascolto di nuove connessioni.
6) Inizia il dialogo con il client connesso, effettuato sul nuovo socket
restituito dalla 'accept()'
7) Alla fine chiude il socket creato dalla 'accept()'. Il master socket ovviamente resta in ascolto... All'arrivo di una nuova connessione si riparte dal punto 5).
Il client:
1) Crea il socket per collegarsi al server
2) definisce l'indirizzo e la porta del server a cui vuole collegarsi (che sono quelli su cui il server è in ascolto...)
3) si connette (tramite la funzione 'connect()')
4) se la 'connect()' ha successo, la connessione è già stabilita con il server. Il dialogo è effettuato utilizzando lo stesso socket usato per la connessione (a differenza del server che usa un socket dedicato, assegnato dalla 'accept()').
5) Alla fine chiudo il socket. Per effettuare una nuova connessione, deve si riparte dal punto 1). Se il server a cui ci si vuole connettere è lo stesso, si può saltare il punto 2), altrimenti (giustamente) bisogna ridefinire l'indirizzo e la porta del nuovo server a cui ci si vuole connettere.
17Qwerty71
25-02-2006, 13:53
Ma possibile che se includo le librerie mi vengono comunque gli errori? :muro:
Non mi riconosce il tipo sockaddr_in ed ho provato a linkare in tutti i modi quelle maledette librerie :cry:
Con il pragma o andando nelle opzioni del CodeBlocks, ma nulla :mad:
Aiutooo :cry:
Ma possibile che se includo le librerie mi vengono comunque gli errori? :muro:
Non mi riconosce il tipo sockaddr_in ed ho provato a linkare in tutti i modi quelle maledette librerie :cry:
Con il pragma o andando nelle opzioni del CodeBlocks, ma nulla :mad:
Aiutooo :cry:
Ma ti dà errore in fase di compilazione o in fase di linking?
Che tipo di errore ti dà?
Stai includendo <winsock2.h> ?
17Qwerty71
25-02-2006, 14:05
Ma ti dà errore in fase di compilazione o in fase di linking?
Che tipo di errore ti dà?
Stai includendo <winsock2.h> ?
Si ho incluso anche la winsock2.h :)
Questi sono gli errori (in Build Log):
Procedure/DlgMainProc.h:136: error: `sockaddr_in' undeclared (first use in this function)
Procedure/DlgMainProc.h:136: error: (Each undeclared identifier is reported only once
Procedure/DlgMainProc.h:136: error: for each function it appears in.)
Procedure/DlgMainProc.h:136: error: syntax error before "sock_addr"
Procedure/DlgMainProc.h:137: error: `sock_addr' undeclared (first use in this function)
Questa è la riga dove mi da l'errore
sockaddr_in sock_addr;
:cry:
Si ho incluso anche la winsock2.h :)
Questi sono gli errori (in Build Log):
Questa è la riga dove mi da l'errore
:cry:
Argh stai commettendo un errore banale. ;)
Il tipo sockaddr_in è una struttura (struct) non definita con la typedef nell'header winsoock2 (winsock2.h).
Quindi, ogni volta che definisci una nuova variabile di tipo sockaddr_in, devi fare:
...
int main(void)
{
...
struct sockaddr_in sockIn;
...
sockIn.sin_family = AF_INET;
... /* eccetera... */
}
EDIT: Puoi sempre fare riferimento ai sorgenti dei programmi che ho postato prima se vuoi, li ho completamente commentati ;)
17Qwerty71
25-02-2006, 14:25
Argh stai commettendo un errore banale. ;)
Il tipo sockaddr_in è una struttura (struct) non definita con la typedef nell'header winsoock2 (winsock2.h).
Quindi, ogni volta che definisci una nuova variabile di tipo sockaddr_in, devi fare:
[CODE]
...
int main(void)
{
...
struct sockaddr_in sockIn;
...
sockIn.sin_family = AF_INET;
... /* eccetera... */
}
EDIT: Puoi sempre fare riferimento ai sorgenti dei programmi che ho postato prima se vuoi, li ho completamente commentati ;)
Grazie, pensavo fosse un'errore dovuto alla non linkaggio della libreria :doh:
Ma come mai non hanno definito la struttura come tipo di variabile (di solito la microsoft le definisce da quello che ho visto)? :confused:
Un'altra domanda: ma l'header windows.h include a sua volta gli header per le winsock (perchè mi funziona anche senza winsock2.h)?
Grazie, pensavo fosse un'errore dovuto alla non linkaggio della libreria :doh:
Ma come mai non hanno definito la struttura come tipo di variabile (di solito la microsoft le definisce da quello che ho visto)? :confused:
Perchè la Microsoft (come tutti gli altri) segue con la sua libreria le specifiche standard dei socket BSD, introdotti la prima volta in ambiente UNIX. Questo garantisce al codice scritto con winsock la portabilità su altri sistemi (a dire il vero non al 100%, ma quasi) e garantisce soprattuto al programmatore che ha imparato a programmare con i scoket di non imparare da zero nuove funzioni/tipi di variabili. poi la microsoft ha introddto per i suoi sistemi un'"estensione" (un nuovo set di specifiche secondo la sua filosofia, al solito...) ai socket BSD (nella libreria mswsock.h, mai usata a dire il vero), ed ha introdotto anche nuovi metodi (disponibili solo per Windows, in altri sistemi si fa diversamente e sono più portabili) per la gestione asincrona dei socket (socket overlapped gestiti con le funzioni WSAxxx, ad esempio WSASocket(), WSAConnect, WSAAccept(), WSAAsyncSelect(), ecc...).
Un'altra domanda: ma l'header windows.h include a sua volta gli header per le winsock (perchè mi funziona anche senza winsock2.h)?
Mi pare di sì, se non sbaglio in windows.h è incluso pure quello, ma non ci metto la mano sul fuoco. Però possono esserci altre ragioni. Prova a non includere né windows.h né winsock2.h e compila. Se funziona, prova anche a togliere la direttiva #pragma. Se tolta anche quella ti dà solo errore di linking (ma continua a compilare) fammi sapere.
Al peggio, puoi sempre spulciare il codice di windows.h.
EDIT: in realtà in ambiente unix/linux, i socket sono un po' più simpatici per il programmatore: essi sono infatti un astrazione del filesystem, quindi un socket viene visto dal programmatore come un file su harddisk. Questo permette di usare un soclet come un file (ad esempio si scrivono dati sul socket con una write(), si leggono dati con una read(), ecc.) In widows ninvece esistono funzioni apposite (send() per scrivere, recv() per leggere, questo per i socket datagram ovviamente).
EDIT 2: se ti rompe definire le variabili sockaddr_in anteponendo come doveroso la keyword struct, puoi fare (all'inizio del codice o in un header ancora meglio):
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
In questo modo potrai definire le variabili così:
SOCKADDR_IN sockIn;
SOCKADDR sock;
fidel sei un capo!!! non ho tempo di replyare degnamente al momento (notte bianca a torino!) ma quando torno ti ringrazio a dovere!
fidel sei un capo!!! non ho tempo di replyare degnamente al momento (notte bianca a torino!) ma quando torno ti ringrazio a dovere!
Troppo buono ;) Anche tu notte bianca? C'ero anch'io ieri sera :D Grande giorno per torino. E' stata una fortuna per me tornare a Torino proprio in questi giorni :cool:
Tornando in topic, se hai ancora problemi fammi sapere, ormai siamo vicini alla soluzione mi sembra ;)
si siamo molto vicini, anche se ho pochissimo tempo da dedicarci in ti giorni che ho parenti che vengono da napoli (devo fare da cicerone e far visitare torino)...cmq con java mi son trovato un attimo meglio (ma con java son piu ferrato)...i tuoi esempi sono una miniera ad ogni modo, me li studio alla perfezione e poi ti dico, ma non dovrei avere piu problemi a sto punto...penso che mi cimentero nella realizzazione di un client per trasferire file fra i miei amici (non credo sia molto laborioso, voglio solo che vada piu veloce di msn, che a me va a 1 k se è tanto), cosi, per esercizio...
si siamo molto vicini, anche se ho pochissimo tempo da dedicarci in ti giorni che ho parenti che vengono da napoli (devo fare da cicerone e far visitare torino)...cmq con java mi son trovato un attimo meglio (ma con java son piu ferrato)...i tuoi esempi sono una miniera ad ogni modo, me li studio alla perfezione e poi ti dico, ma non dovrei avere piu problemi a sto punto...penso che mi cimentero nella realizzazione di un client per trasferire file fra i miei amici (non credo sia molto laborioso, voglio solo che vada piu veloce di msn, che a me va a 1 k se è tanto), cosi, per esercizio...
Beh con Java ti sarai trovato meglio perchè è totalmente a oggetti ;) Pero' con l'API di win utilizzata direttamente in C hai il massimo controllo e flessibilità.
Non credo avrai problemi per fare un programma per trasferire file, il concetto è sempre lo stesso, basta leggere il file da mandare in "chunks" di dimensione stabilita, e fare una send() su ogni chunk in un ciclo while (finchè viene letto tutto il file). Stessa cosa per il server (legge dal socket finche' lo stesso non ritorna 0 bytes letti).
Un consiglio (scontato): quando hai dubbi di sorta o quando vuoi approfondire l'uso di una funzione (valori di ritorno, comportamento ecc.) consulta la MSDN, è un'ottima e completa fonte di informazioni.
Se avrai dei dubbi nella realizzazione del tuo programma in futuro, basta chiedere, quando ho tempo rispondo volentieri (quando so rispondere eheh) ;)
Ciao e buon giro!
17Qwerty71
02-03-2006, 17:34
E' possibile passare in sin_addr l'identificativo del pc della rete locale invece dell'ip? :confused:
Fenomeno85
02-03-2006, 18:25
E' possibile passare in sin_addr l'identificativo del pc della rete locale invece dell'ip? :confused:
penso che basta mettere in inet_addr il nome ... se non funziona allora ci sarà il modo facendo una richiesta al DNS.
~§~ Sempre E Solo Lei ~§~
E' possibile passare in sin_addr l'identificativo del pc della rete locale invece dell'ip? :confused:
Assolutamente no. inet_addr poi non può essere usata nel modo detto da Fenomeno85 (inet_addr prende come parametro una stringa contenente l'ip in notazione puntata).
Se vuoi ottenere l'indirizzo ip del server su cui connettersi tramite il suo nome DNS si usa la funzione
struct hostent* FAR gethostbyname(
const char* name
);
Per comodità metto anche la struttura hostent:
typedef struct hostent {
char FAR* h_name;
char FAR FAR** h_aliases;
short h_addrtype;
short h_length;
char FAR FAR** h_addr_list;
} hostent;
(tutti quei FAR sono definiti in Win, fai conto che non ci sono).
In più in winsock2.h è definita, per retrocompatibilità:
#define h_addr_list[0] h_addr
Ad esempio puoi fare:
struct sockaddr_in clientSin;
struct hostent *server;
char serverName[20];
...
// Non alloco memoria per '*server', dal momento che la struttura
// viene allocata dalla funzione...
strncpy(serverName, "www.google.it", 20);
server = gethostbyname(serverName);
...
// Se tutto è andato bene, ora in '*server' ho, tra le altre cose, la
// lista di indirizzi IP associati al nome host www.google.it.
// Ad esempio, per prendere il primo:
clientSin.sin_addr = *((struct in_addr *)server->h_addr_list[0]);
// Potevo anche fare:
// clientSin.sin_addr = *((struct in_addr *)server->h_addr);
Volendo puoi anche usare la seguente funzione:
int getaddrinfo(
const char* nodename,
const char* servname,
const struct addrinfo* hints,
struct addrinfo** res
);
Per il suo uso ti rimando alla MSDN (o alla manpage di Linux indifferentemente).
Se invece vuoi risolvere gli ip tramite il nome NetBios del PC (il nome di Windows per intenderci) ovviamente lo puoi fare solo in rete locale, quando non hai un server DNS in LAN oppure la tua lan non è collegata al DNS mondiale (sennò usi gethostbyname tranquillamente). Per quello non ricordo cosa si usa, poso controllare (sarà qualche funzione esclusiva di winsock2).
EDIT: penso puoi provare questa funzione per sapere l'ip tramite il nome NetBios:
NET_API_STATUS NetWkstaTransportEnum(
LPWSTR servername,
DWORD level,
LPBYTE* bufptr,
DWORD prefmaxlen,
LPDWORD entriesread,
LPDWORD totalentries,
LPDWORD resumehandle
);
definita in <Lm.h>
Consulta al solito MSDN per il suo uso (cmq alla fine in *bufptr hai tutte le info che ti servono, incluso l'ip).
EDIT 2: Però mi sta venendo un'idea: prova a passare a gethostbyname il nome Netbios del pc a cui collegarti invece del nome DNS, magari funziona lo stesso! Ovviamente devi anteporre "\\" al nome (ad esempio se il pc si chiama MioPc, devi fare gethostbyname("\\MioPc"). E' possibile che la gethostbyname con macchine Windows si comporti in modo "esteso", magari hai una bella sorpresa!
Quando posso provo anch'io.
Ho provato ciò che ho detto nell'EDIT 2 del post precedente.
Funziona alla grande con gethostbyname() ;)
Però preciso una cosa non corretta che ho detto prima: il nome del Pc NON deve essere prefisso con "\\". Ti basta quindi fare:
struct hostent *server;
...
server = gethostbyname("MioPc");
// Oppure gli passi il nome con un buffer come ho fatto nell'esempio
// precedente, di solito si usa il buffer dal momento che non sai praticamente
// mai a priori il server a cui vuoi connetterti ;)
Ah, ovviamente questo vale per reti Windows, oppure per reti Linux dotate di Samba.
Buon divertimento :)
17Qwerty71
02-03-2006, 20:55
Grazie mille ;)
Fenomeno85
03-03-2006, 10:13
Assolutamente no. inet_addr poi non può essere usata nel modo detto da Fenomeno85 (inet_addr prende come parametro una stringa contenente l'ip in notazione puntata).
Se vuoi ottenere l'indirizzo ip del server su cui connettersi tramite il suo nome DNS si usa la funzione
se non ricordo male però almeno localhost lo faceva :D
~§~ Sempre E Solo Lei ~§~
se non ricordo male però almeno localhost lo faceva :D
~§~ Sempre E Solo Lei ~§~
Quello è possibile, ma localhost è un nome speciale per l'interfaccia di loopback ;)
Fenomeno85
03-03-2006, 12:23
Quello è possibile, ma localhost è un nome speciale per l'interfaccia di loopback ;)
si ok ma non sapevo se funziona anche con altro :D
~§~ Sempre E Solo Lei ~§~
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.