Ultima modifica:
Per chi ha installato Microsoft Windows Office Word 2007/2010 sul proprio computer consiglio di scaricare il file docx della guida (Reuploaded on Mediafire):
DOWNLOAD GUIDA - MEDIAFIRE
In questa guida cercherò di spiegarvi come connettere due programmi (il client e il server) distanti fra loro, su due computer diversi, attraverso i sockets.
Il client (cliente) è il programma che possiedono molti utenti e che riceve e invia informazioni al server, che possiede un'unica persona, solitamente il creatore stesso, che mette in comunicazione tra loro i vari client.
I sockets possono essere considerati come dei “fogli” che vengono passati dal client al server e viceversa, attraverso internet, e su questi “fogli” vengono scritte le informazioni che il client vuole comunicare al server e viceversa.
Ogni macchina, anche il vostro computer, è connesso alla rete attraverso delle porte. Queste porte sono i canali dove passano le connessioni.
Ad esempio, solitamente i browser (Internet Explorer, Mozilla Firefox, Google Chrome, Opera) connettono alla rete attraverso la porta 8080.
Per spiegazioni più dettagliate vi consiglio di leggere alcune brevi pagine di Wikipedia:
Sistema client/server - Wikipedia
Socket (reti) - Wikipedia
Porta (reti) - Wikipedia
Creazione del Server
Cominciamo a creare il server:
Creiamo un nuovo progetto: scegliamo come modello Applicazione Windows Form (selezionata per default) e chiamiamolo Server.
Nel nostro Form inseriamo due TextBox, una con nome TextBox1 e l’altra TextBox2.
Andiamo alla proprietà Multiline della TextBox2 e settiamola su True.
A questo punto noi possiamo allungare la TextBox anche verso il basso.
Adesso inseriamo un Button vicino alla TextBox1 con nome Button1, e nella sua proprietà Text inseriamo “INVIA”.
Adesso inseriamo due Timer con nome Timer1 e Timer2.
Adesso prendiamo anche il controllo WindowsMediaPlayer e disegniamolo all’interno del Form.
Cosa?!? WindowsMediaPlayer?!?
Certo. Per inserirlo non dovete prendere il programma e provare a buttarlo dentro al Form
ma andate nella casella degli strumenti (è la finestra dove prendere i Button e le TextBox) e cliccate con il tasto destro del mouse in un punto a caso e scegliete Scegli elementi…
Nella finestra che compare andate nella scheda Componenti COM e scorrete in basso fino ad arrivare a Windows Media Player, spuntatelo, e il controllo vi comparirà nella casella degli strumenti.
Dopo averlo disegnato (il controllo WindowsMediaPlayer non è necessario ma mi serve per farvi capire cosa si può fare con le connessioni Client-Server), andiamo nel codice del Form.
Prima di cominciare dobbiamo importare due librerie:
-System.Net.Sockets che è la libreria per gestire le comunicazioni attraverso i Sockets.
-System.Text.UTF8Encoding libreria utile per convertire le informazioni da byte a testo “leggibile dai comuni mortali”.
Per importarle dovremo scrivere sopra tutto il codice (anche sopra Public Class Form1) queste due righe:
Adesso dichiariamo tre variabili globali, dovremo quindi inserirle subito sotto Public Class Form1. Le variabili sono le seguenti:
Con servitore chiameremo il nostro server e con cliente il nostro client. flusso saranno invece le informazioni che viaggeranno sui sockets, e che dovremo leggere/scrivere.
Nell’evento Load del Form, ovvero in Form1.Load, scriviamo:
Il codice è commentato, dovreste quindi essere in grado di capirlo.
Adesso andiamo nell’evento Tick del Timer2 (Timer2.Load), che abbiamo avviato al Load del Form, e scriviamo:
Servitore.Pending() controlla se ci sono delle richieste di connessione in sospeso, ovvero se qualche client sta tentando di connettere.
cliente = servitore.AcceptTcpClient() con questa riga viene detto di accettare la connessione, e cliente d’ora in poi sarà questo client di cui abbiamo accettato la connessione.
flusso = cliente.Get.Stream() Stream è il flusso di dati. Questa riga significa quindi che il flusso di dati con cliente d’ora in poi verrà chiamato flusso.
Appena c’è un connessione troviamo Timer2.Stop().
State attenti che anche se si trova all’inizio le istruzioni dopo vengono comunque eseguite. L’unica differenza è che al termine delle istruzioni il Timer non ripartirà.
Con questo codice abbiamo anche fatto partire il Timer1. Andiamo adesso a programmare il suo evento Tick (Timer1.Tick), e inseriamo:
cliente.Available restituisce un Integer (un numero intero) che corrisponderà al numero di dati ricevuti da cliente e disponibili per essere letti. Se questo numero è maggiore di 0 significa, in sostanza, che il client ha inviato dei dati al server.
Dim temp(cliente.Available – 1) As Byte significa che l’array temp è di tipo byte ed è di dimensioni uguali al numero di informazioni che devo ricevere dal client meno 1.
flusso.Read(temp, 0, temp.Length) significa: leggi il byte del flusso dalla posizione zero (dall’inizio) fino alla lunghezza di temp (ovvero fino alla fine del numero di byte da ricevere) e scrivi queste informazioni in temp.
A questo punto temp conterrà le informazioni che ci ha inviato il client in forma di bytes.
Dim testo As String = UTF8.GetString(temp) con questa riga ho convertito tutti i bytes di temp in UTF8 e ho messo questa stringa dentro alla variabile testo.
Questo testo verrà poi scritto nella TextBox2.
Possiamo anche poi aggiungere, sotto al codice scritto prima (sotto End If), queste righe:
AxWindowsMediaPlayer.URL = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + “/song.mp3”
E questa riga che fa?!?
È più semplice di quanto sembra. Inserisce come canzone da riprodurre nel controllo WindowsMediaPlayer il file song.mp3 contenuto nel Desktop.
Infatti System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) è la directory (il percorso) del Desktop, in qualsiasi computer.
Se voi cambiate l’ultima parte (DesktopDirectory) potete scegliere altri percorsi, validi in tutti i computer, anche se le cartelle hanno nomi diversi.
AxWindowsMediaPlayer1.Ctlcontrols.play() avvia la musica, e con stop() viene fermata.
In sostanza il codice sopra significa:
Se il client ha inviato “start music” allora fai partire la musica (file song.mp3 che è nel desktop).
Se ha invece inviato “stop music” allora ferma la riproduzione.
Adesso ci manca da programmare l’evento Click del Button1 (Button1.Click), il tasto per inviare informazioni al client: al suo interno scriviamo:
Se avete capito la parte della ricezione di dati dovreste capire anche questa parte (invio di dati) solo con l’aiuto dei commenti. Il procedimento è lo stesso, solo che vengono inviati i dati e non letti.
Il risultato finale dovrebbe essere questo:
Bene. Abbiamo finito il nostro server!!! Adesso dobbiamo creare il client. Salviamo e chiudiamo il progetto del server.
Creazione del Client
Creiamo un nuovo progetto, scegliamo come modello Applicazione Windows Form, e chiamiamolo Client.
Nel nostro Form inseriamo una TextBox (nome: TextBox1) e accanto mettiamo un Button (nome: Button1; Proprietà Text: “CONNETTI”).
Sempre vicino a questo button mettiamo una CheckBox (nome: CheckBox1; Proprietà Text: “HostName?”).
Un po’ più un basso mettiamo un’altra TextBox (nome: TextBox2), accanto a questa un altro Button (nome: Button2; Proprietà Text: “INVIA”), e subito sotto un’altra TextBox (nome: TextBox3; Proprietà Multiline: True).
Mettiamo anche un Timer (nome: Timer1).
Importiamo le stesse librerie che avevamo importato anche nel server:
Adesso dichiariamo due variabili globali:
La variabile del server (servitore) non ci servirà nel client.
Adesso andiamo a programmare l’evento Click del Button1 (Button1.Click):
Con questo codice inizialmente viene messo dentro alla variabile AddressIP il testo della TextBox1 (che sarà l’IP del server a quale l’utente vuole connetere).
Poi viene però effettuato un controllo: se la CheckBox1 è spuntata allora esegue una lunga serie di istruzioni e poi inserisce un altro valore in AddressIP.
In questo If viene preso l’indirizzo IP di un HostName e viene messo in AddressIP.
Un HostName è un nome che “sostitusce” l’indirizzo IP.
Un esempio è google.it (senza http://www.). Quando voi inserite google.it nel vostro browser verrete indirizzati alla home di google.
Ma provate ora a scrivere nelle barra degli indirizzi del vostro browser 209.85.147.103, e vedete che verrete indirizzati di nuovo a google, infatti 209.85.147.103 è l’indirizzo IP del server di google.
Per ricavare l’indirizzo IP di un Host potete aprire il prompt dei comandi di windows (Start --> Esegui… --> cmd.exe) e digitare ping google.it
Quello che compare tra le parentesi tonde è l’IP del server (in questo caso del server di google).
Quindi se la CheckBox1 è spuntata il nostro programma prende l’IP dell’HostName inserito invece di considerare quello che è stato scritto come indirizzo IP.
cliente.Connect(AddressIP, 8888) Con questa riga il client si connette al server che ha l’IP che è contenuto in AddressIP attraverso la porta 8888.
Dopo esegue un controllo e se è connesso chiama flusso il flusso di dati client-server (come nel server) e scrive nella TextBox3 che è connesso. Altrimenti scrive nella TextBox3 che il server non risponde.
Con questo abbiamo anche avviato il Timer1. Andiamo a programmare il suo evento Tick (Timer1.Tick):
Se avete capito il codice del server, questo per voi non sarà un problema capirlo da soli.
Adesso andiamo a programmare l’evento Click del Button2 (Button2.Click):
Anche questo dovreste essere in grado di capirlo da soli.
Bene… Il risultato finale dovrebbe essere questo:
Adesso abbiamo creato anche il Client (salviamo il progetto e chiudiamolo). Non ci resta che far connettere il client con il server.
Ci sono tre diversi tipi di connessione:
Connessione su stesso computer: La connessione tra il client e il server viene effettuata sullo stesso computer. Adatto se si vuole vedere il funzionamento del programma.
Connessione su due computer nella rete locale: La connessione tra il client e il server viene effettuata su due computer differenti, ma questi computer sono connessi alla stessa rete (di solito mediante un router). Adatto se si vuole vedere il funzionamento del programma e si hanno a disposizione due computer è un router.
Connessione remota su due computer: La connessione tra il client e il server viene effettuata su due computer differenti che sono connessi ad internet e si possono trovare in qualsiasi parte del pianeta. Adatto se si vuole far connettere due computer distanti.
Una cosa che mi sono scordato di farvi notare è che la connessione viene effettuata attraverso la porta 8888. Questa porta, se si vuole cambiarla, deve essere cambiata sia nel client che nel server.
Connessione su stesso computer
Avviamo sia il nostro server che il client (prima compilateli, o eseguiteli tutti e due all’interno del debugger di Visual Studio).
Se tutto va bene nel server dovrebbe comparire la scritta “Server avviato!”.
N.B.: è possibile che il vostro firewall blocchi la connessione. Se è così dovrete sbloccarla o disattivare il firewall.
Nella TextBox1 del client mettiamo 127.0.0.1
127.0.0.1 è l’IP del computer stesso. Un computer per indicare se stesso usa sempre 127.0.0.1. Diciamo così al nostro client di connettere a questo stesso computer.
Adesso clicchiamo su connetti.
Se tutto va bene sia il client che il server dovrebbero segnalare che si sono connessi.
Adesso potete scrivere messaggi dal server al client e viceversa. Inoltre se dal client inviate “start music” il server farà partire la musica che avete scelto, se scrivete invece “stop music” la fermerà.
Connessione su 2 computer nella rete locale
Avviate su un computer il client e sull’altro il server.
Adesso nel computer dove avete avviato il server aprite il prompt dei comandi di windows e scrivete ipconfig
Visualizzerete una lunga serie di scritte che per molto di voi saranno anche incomprensibili.
Dovreste però trovare scritto da qualche parte una cosa tipo:
Indirizzo IPv4 oppure Indirizzo IP e accanto trovate scritto l’IP della rete locale.
L’IP della rete locale comincia sempre con 192.168 e poi ci sono 2 numeri che variano da computer a computer, da rete a rete.
Nella TextBox1 del client mettiamo quell’IP e clicchiamo su connetti.
Se tutto va bene sia il client che il server dovrebbero segnalare che si sono connessi.
Adesso potete scrivere messaggi dal server al client e viceversa. Inoltre se dal client inviate “start music” il server farà partire la musica che avete scelto, se scrivete invece “stop music” la fermerà.
Connessione remota su due computer
Dobbiamo prima avere un indirizzo IP statico per poterlo fare. Per avere un Indirizzo IP statico ci sono due modi:
-Contattare il proprio provider e chiedere che ci venga assegnato un indirizzo IP statico (è necessario un pagamento).
-Utilizzare un comodo servizio chiamato DynDNS (completamente gratuito).
Ovviamente io vi spiegherò il secondo metodo ;-).
Aprite il vostro browser, andate su http://www.dyndns.com e registratevi (Sign In --> Create an Account).
Quando vi siete registrati, andate su My Account o My Services e cercate Add Host Services (dovrebbe essere nella scheda My Services).
Cliccate su quel link e nella pagina che vi verrà mostrata inserite come HostName quello che preferite, come Service Type mettete Host with IP address e come IP Address mettete quello che leggete subito sotto (vi basta cliccare su quel link per inserirlo automaticamente).
Adesso cliccate su Add To Cart (tranquilli tutto gratuito) e poi su Next.
A questo punto avete aggiunto al vostro ip un HostName. Ma il vostro IP non è ancora “statico”.
Esattamente quello che faremo non è rendere il vostro IP statico ma far si che anche se il vostro IP è dinamico (cioè cambia in continuazione) attraverso l’HostName potrete sempre connettere all’IP, qualunque esso sia.
Per fare ciò dobbiamo scaricare un programma che si chiama DynDNS Updater.
Per scaricarlo cliccate su Support e poi su Download Now (oppure direttamente da QUI ).
Appena scaricato spuntate la casella del vostro HostName che avete appena creato e poi su Apply.
Adesso potete anche minimizzare l’applicazione che continuerà ad aggiornare l’Host con il vostro nuovo IP ogni volta che cambia.
Non è ancora finita. Per far si che il server e il client possano comunicare deve essere aperta la porta 8888 (quella che abbiamo scelto per farli connettere, potete cambiarla con un'altra qualsiasi se volete).
Di solito non è necessario aprirla anche nel client, ma se non funzionasse provate ad aprirla anche nel computer dove è situato il client.
Comunque per aprirla (sia che sia il computer con il server che quello con il client) dovrete aprire il vostro browser e digitare nella barra degli indirizzi il vostro HostName che prima avete creato (se non funzionasse potete inserire l’indirizzo del vostro Gateway (Gateway predefinito), che visualizzate scrivendo ipconfig nel prompt dei comandi di windows).
Accedete al pannello di controllo (spesso l’id e la password sono admin e admin, ma comunque vi deve essere stata fornita quando avete comprato il vostro modem/router) e cercate il punto dove potete aprire le vostre porte (non è sempre così facile trovarlo, io l’ho ad esempio in Avanzate --> Inoltro delle porte).
Di solito chiedono:
Nome applicazione: Inserite quello che volete, ad esempio ProvaConnessione.
Indirizzo IP: Inserite l’indirizzo IP del vostro computer sulla rete locale (quello che inizia con 192.168; attenzione: non dovete inserire quello del Gateway).
TCP(Porta Esterna): mettete 8888
UDP(Porta Esterna): 8888
TCP(Porta Enterna): 8888
UDP(Porta Enterna): 8888
Al termine salvate le modifiche (a volte è anche necessario riavviare il modem/router).
Una comoda alternativa è di utilizzare una piccola utility chiamata PortMap. Potete scaricarla da qui:
MEGAUPLOAD - The leading online storage and file delivery service
Scansione VirusTotal[8/41]:
VirusTotal - Free Online Virus, Malware and URL Scanner
Essendo un programma che apre delle porte, molti antivirus lo rilevano come virus.
All'interno del file rar troverete 2 file: un txt che è il file di configurazione; un eseguibile che all'avvio dovrebbe aprire le porte come impostato nel file di configurazione.
Dovrete cambiare l'outerIP e cose varie.
Ometto la spiegazione dettagliata su come utilizzare PortMap.
Adesso che abbiamo aperto anche la porta non ci basta che avviare il client e il server e provare.
Nella TextBox1 del client mettete l’HostName che avete scelto prima, spuntate la CheckBox, e poi cliccate su connetti.
Se tutto va bene sia il client che il server dovrebbero segnalare che si sono connessi.
Adesso potete scrivere messaggi dal server al client e viceversa. Inoltre se dal client inviate “start music” il server farà partire la musica che avete scelto, se scrivete invece “stop music” la fermerà.
Importanti informazioni su DynDNS
Spesso potrebbe verificarsi che, dopo aver aperto l'host su DynDNS, se cercate di aprire determinate pagine web potreste non visualizzarla perchè DynDNS vi impedisce di aprire quella pagina.
è possibile ovviamente risolvere questo problema ma.... se lo fate i client non potranno più connettere al vostro server e voi perderete il vostro "ip statico" (ma non per sempre, potete rimetterlo quando volete, ma se lo rimettete quelle pagine torneranno a essere bloccate).
Per risolverlo dovrete:
1- Chiudere DynDNS Updater.
2- Andare in Pannello di controllo --> Centro connessioni di rete e condivisione --> Modifica impostazioni scheda --> cliccate con il destro sulla vostra scheda di rete e premete su Proprietà --> Selezionate Protocollo Internet versione 4 (TCP/IPv4) --> Togliete i due server DNS e sostituiteli con altri (magari inserite Ottieni indirizzi server DNS automaticamente).
Modificare il server per la multiconnessione
Abbiamo fino ad ora imparato come connettere un client ad un server.
Ma i veri server (game server, server di messaggistica istantanea (Skype, MSN, ecc.), server di siti web, ecc.) funzionano diversamente:
Invece di far connettere un solo client, fanno connettere più client. Ci sono 2 modalità di connessione (o meglio modalità di scambio di informazioni):
Nella prima, i vari client connettono al server che scambia informazioni con questi mantenendo “autonomo” il contatto con ognuno di loro.
Ovvero i client connettono al server, inviano, ma più spesso, scaricano informazioni dal server e tutto finisce qui. Le informazioni che circolano ad esempio tra il client A e il server sono completamente separate da quelle che circolano tra il client B e il server.
Nella seconda, invece, i vari client connettono al server, e poi attraverso quest’ultimo, scambiano informazioni tra di loro (è il funzionamento dei server di messaggistica istantanea, o, se vogliamo, anche dei server mail, quelli che gestiscono la posta elettronica).
Le informazioni che partono dal client A, arrivano al server che le invia al client B.
In questa parte della guida impareremo proprio a creare un sistema di messaggistica istantanea (se imparerete bene a fare questo, non avrete difficoltà a modificare il codice come meglio serve a voi, e magari anche a trasformarlo nella prima modalità se vi è necessario).
Per fare ciò ci basterà andare a modificare alcune parti del server (il client funziona benissimo così).
In particolare dovremo semplicemente trasformare la variabile cliente in un array così che possa contenere più client invece che uno solo, poi dovremo modificare il sistema di ricezione e invio delle informazioni.
Per fare ciò direi di riprendere da zero la creazione del server.
Al termine del lavoro sarà possibile:
-Inviare informazioni tra un client e l’altro attraverso il server, e il server inoltre potrà inviare informazioni a tutti i client quando lo vorrà il proprietario.
Allora, mettiamo al lavoro.
Mi scuso se il codice non funziona ma non l’ho testato e inoltre l’ho scritto direttamente sul web. Ho comunque ricontrollato il codice è sembra essere corretto. In caso di problemi vi prego di segnalarli.
Creiamo un nuovo progetto, scegliamo come modello Applicazione Windows Form e come nome mettiamo MultiConnectionServer.
Inseriamo gli stessi controlli che avevamo inserito nel vecchio server tranne il controllo WindowsMediaPlayer (tanto ormai avete capito come funziona).
I controlli, con le rispettive proprietà da modificare, erano:
-TextBox1
-Button1 --> Proprietà Text: “INVIA”
-TextBox2 --> Proprietà Multiline: True (allungate poi la TextBox verso il basso).
-Timer1 e Timer2
Adesso importiamo di nuovo le solite librerie:
Ricreiamo le variabili globali:
Noterete una cosa che a molto sembrerà strana. Le variabili cliente e flusso le ho trasformate in array (cosa che avevo già annunciato), ma la cosa che forse non avete mai visto è la particolare dimensione che ho inserito a questi array. -1?!? Bhè è come se non esistesse. Le dimensioni degli array, spero lo sappiate già, partono da 0, quindi -1 è una dimensione nulla. Vi spiegherò più avanti come mai ho inserito questa particolare dimensione.
Adesso andiamo a programmare l’evento Load del Form (Form1.Load). Il codice sarà uguale a quello del server normale, ovvero:
Adesso passiamo subito all’evento Tick del Timer2, e qui vi spiegherò la dimensione degli array.
Allora…
Con Array.Resize ridimensiono sia l’array cliente che l’array flusso aggiungendo uno. Ora dovreste capire perché ho messo -1 come dimensione inziale. Perché il primo client che si connette andrà a piazzarsi della posizione 0 dell’array. Se avessi messo 0 come dimensione iniziale allora il primo client si sarebbe piazzato alla posizione 1, lasciando vuota la posizione 0, che avrebbe poi potuto generare un’eccezione (in particolare: NullReferenceException) se avessimo cercati di richiamare cliente(0).
La stessa cosa vale per l’array flusso.
Per il resto è tutto uguale al server a connessione singola.
Adesso andiamo all’evento Tick del Timer1 (Timer1.Tick).
Qui dovremmo far si che ogni dato che viene ricevuto dal server, venga rinviato da quest’ultimo a tutti i client connessi (quelli che sono all’interno dell’array cliente). Ecco il codice:
Con questo codice viene preso un client e si controlla se sta inviando delle informazioni.
Se sta inviando informazioni allora si procede, altrimenti viene controllato un altro client.
Se il client che si sta controllando (cliente(r)) sta inviando informazioni, vengono ricevute byte per byte all’interno dell’array temp e vengono scritte nella TextBox2 con il relativo numero del client che ha scritto (“Client(“ + r.ToString + “): “), così il server può visualizzare chi ha inviato il messaggio.
Poi per ogni client connesso i dati ricevuti da cliente(r), che sono stati messi in temp, vengono scritti al client (flusso(s)).
Bene. Dovreste essere in grado di capire
soprattutto chi è più esperto nel gestire gli array (l’unica difficolta di questo codice può essere questa).
Adesso programmiamo l’evento Click del Button1 (Button1.Click):
Se avete capito il codice sopra, questo è una sciocchezza 
Bene. Abbiamo finito il nostro server. Il risultato finale dovrebbe essere questo:
Salvate il progetto e provatelo. Funziona esattamente come il server a connessione singola, con l’unica differenza che ogni informazione che viene inviata al server dal client viene re-inviata a tutti i client.
Potrete notare un “problemino”: ovvero quando scrivete qualcosa dal client nella TextBox del client dove vi vengono raccolti tutti i messaggi vi comparirà 2 volte lo stesso messaggio.
Questo perché una volta viene scritto sul client dallo stesso client. E l’altra dal server che risponde anche a te stesso.
Per risolverlo dovrete fare qualche modifica nel client e togliere la parte dove viene scritto ciò che inviate, oppure nel server e aggiungere di non inviare il messaggio allo stesso client che lo ha inviato.
Altro problema è che quando il Client(0) invia un messaggio a Client(1) viene scritto che è stato inviato da Server. Questo potete risolverlo facendo assegnare dal server un ID (un identificatore univoco) ad ogni client che si connette (potete utilizzare la dimensione stessa dell’array cliente), e il server deve poi inviare a tutti il client anche questo ID agli altri client che così potranno sapere chi ha inviato il messaggio.
EDIT: Risolti i problemi sopra citati. Riporto il messaggio in cui l'ho risolti:
Inviare file tra client e server
[/FONT] [FONT=&]Dopo aver stabilito la connessione client/server, oltre che ad inviare messaggi testuali, potete inviare inviare dei file.
Per fare ciò dovrete prendere i bytes che arrivano dal server/client e con questi scrivere un file.
Nell'esempio facciamo un piccolo invio da server a client.
Nel momento in cui volete ricevere il file mettete:[/FONT]
[FONT=&]WriteAllBytes serve a scrivere dei bytes in un file.
basta cambiare "file.ext" con il nome e l'estensione che si vuole dare al file.
Per inviare il file invece:[/FONT]
[FONT=&]
[/FONT]
[FONT=&]ReadAllBytes legge invece tutti i bytes di un file.[/FONT][FONT=&]
[/FONT][FONT=&]Non credo siano necessarie ulteriori informazioni.
N.B.: Il codice non è testato. Se qualcuno ha dei problemi e me li segnalasse gliene sarei molto grato.[/FONT]
[FONT=&]Video Guida[/FONT][FONT=&]
[/FONT][FONT=&]Questi video guida vi potranno essere utili per capire meglio come funziona.
In questi video viene solo spiegato come eseguire una connessione tra un client e un server (non una multiconnessione).
Noterete che il codice è simile (non uguale), è infatti da qui che ho imparato (rigrazio Niktor per i suoi semplici ma utilissimi video) e ho poi ricreato il codice da 0 cercando di risolvere i vari problemi.
Infatti il codice di NiktorTheNat (creatore di questi video) non funziona correttamente, e presenta qualche bug.
Vi consiglio quindi di non sostituire questi video alla guida che ho scritto qui sopra ma di seguirli entrambi, in modo da capire bene e vedendo il codice come viene scritto dal video e eliminare gli errori e approfondire meglio i vari passaggi che esegue il codice con la guida scritta.
Ecco i video:
[YOUTUBE]vvxgQidMTfM[/YOUTUBE]
[YOUTUBE]VJmIWxezdtc[/YOUTUBE]
[YOUTUBE]dlMYdkZPzFc[/YOUTUBE]
[YOUTUBE]x5eEg4xiL4c[/YOUTUBE]
[/FONT]
La guida è terminata, spero vi sia stata utile ;-)
Se avete problemi o domande non esitate a chiedere (in questa discussione o con un PM).

[GUIDA] Connettere il client al server con i sockets in vb.net by SpeedJack is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
Based on a work at www.inforge.net
[FONT=&]
[/FONT]
DOWNLOAD GUIDA - MEDIAFIRE
In questa guida cercherò di spiegarvi come connettere due programmi (il client e il server) distanti fra loro, su due computer diversi, attraverso i sockets.
Il client (cliente) è il programma che possiedono molti utenti e che riceve e invia informazioni al server, che possiede un'unica persona, solitamente il creatore stesso, che mette in comunicazione tra loro i vari client.
I sockets possono essere considerati come dei “fogli” che vengono passati dal client al server e viceversa, attraverso internet, e su questi “fogli” vengono scritte le informazioni che il client vuole comunicare al server e viceversa.
Ogni macchina, anche il vostro computer, è connesso alla rete attraverso delle porte. Queste porte sono i canali dove passano le connessioni.
Ad esempio, solitamente i browser (Internet Explorer, Mozilla Firefox, Google Chrome, Opera) connettono alla rete attraverso la porta 8080.
Per spiegazioni più dettagliate vi consiglio di leggere alcune brevi pagine di Wikipedia:
Sistema client/server - Wikipedia
Socket (reti) - Wikipedia
Porta (reti) - Wikipedia
Creazione del Server
Cominciamo a creare il server:
Creiamo un nuovo progetto: scegliamo come modello Applicazione Windows Form (selezionata per default) e chiamiamolo Server.
Nel nostro Form inseriamo due TextBox, una con nome TextBox1 e l’altra TextBox2.
Andiamo alla proprietà Multiline della TextBox2 e settiamola su True.
A questo punto noi possiamo allungare la TextBox anche verso il basso.
Adesso inseriamo un Button vicino alla TextBox1 con nome Button1, e nella sua proprietà Text inseriamo “INVIA”.
Adesso inseriamo due Timer con nome Timer1 e Timer2.
Adesso prendiamo anche il controllo WindowsMediaPlayer e disegniamolo all’interno del Form.
Cosa?!? WindowsMediaPlayer?!?
Certo. Per inserirlo non dovete prendere il programma e provare a buttarlo dentro al Form
ma andate nella casella degli strumenti (è la finestra dove prendere i Button e le TextBox) e cliccate con il tasto destro del mouse in un punto a caso e scegliete Scegli elementi…Nella finestra che compare andate nella scheda Componenti COM e scorrete in basso fino ad arrivare a Windows Media Player, spuntatelo, e il controllo vi comparirà nella casella degli strumenti.
Dopo averlo disegnato (il controllo WindowsMediaPlayer non è necessario ma mi serve per farvi capire cosa si può fare con le connessioni Client-Server), andiamo nel codice del Form.
Prima di cominciare dobbiamo importare due librerie:
-System.Net.Sockets che è la libreria per gestire le comunicazioni attraverso i Sockets.
-System.Text.UTF8Encoding libreria utile per convertire le informazioni da byte a testo “leggibile dai comuni mortali”.
Per importarle dovremo scrivere sopra tutto il codice (anche sopra Public Class Form1) queste due righe:
Codice:
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Net.Sockets [COLOR=green]'Libreria per gestire i sockets[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Text.[COLOR=#2b91af]UTF8Encoding[/COLOR] [COLOR=green]'Libreria per decodificare in UTF8[/COLOR][/FONT]
Codice:
[COLOR=blue][FONT=Consolas] Dim[/FONT][/COLOR][FONT=Consolas] servitore [COLOR=blue]As[/COLOR] [COLOR=#2b91af]TcpListener[/COLOR] [COLOR=green]'Variabile server[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] cliente [COLOR=blue]As[/COLOR] [COLOR=#2b91af]TcpClient[/COLOR] [COLOR=green]'Variabile client[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] flusso [COLOR=blue]As[/COLOR] [COLOR=#2b91af]NetworkStream[/COLOR] [COLOR=green]'Variabile del flusso di dati client-server[/COLOR][/FONT]
Nell’evento Load del Form, ovvero in Form1.Load, scriviamo:
Codice:
[FONT=Consolas] servitore = [COLOR=blue]New[/COLOR] [COLOR=#2b91af]TcpListener[/COLOR](8888) [COLOR=green]'servitore è un nuovo server che riceve/invia dati su porta 8888[/COLOR][/FONT]
[FONT=Consolas] servitore.Start() [COLOR=green]'Avvio server[/COLOR][/FONT]
[FONT=Consolas] Timer2.Start() [COLOR=green]'Avvio Timer2[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Server avviato!"[/COLOR] & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
Adesso andiamo nell’evento Tick del Timer2 (Timer2.Load), che abbiamo avviato al Load del Form, e scriviamo:
Codice:
[FONT=Consolas] [COLOR=blue]If[/COLOR] servitore.Pending() [COLOR=blue]Then[/COLOR] [COLOR=green]'Se ci sono richieste di connessione in sospeso allora...[/COLOR][/FONT]
[FONT=Consolas] Timer2.Stop() [COLOR=green]'Stop Timer2[/COLOR][/FONT]
[FONT=Consolas] cliente = servitore.AcceptTcpClient() [COLOR=green]'Accetta la connessione in sospeso[/COLOR][/FONT]
[FONT=Consolas] flusso = cliente.GetStream() [COLOR=green]'Flusso è l’invio/ricezione (Stream) di dati con cliente[/COLOR][/FONT]
[FONT=Consolas] Timer1.Start() [COLOR=green]'Avvia Timer1[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Si è connesso un utente in data "[/COLOR] & Now() & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
cliente = servitore.AcceptTcpClient() con questa riga viene detto di accettare la connessione, e cliente d’ora in poi sarà questo client di cui abbiamo accettato la connessione.
flusso = cliente.Get.Stream() Stream è il flusso di dati. Questa riga significa quindi che il flusso di dati con cliente d’ora in poi verrà chiamato flusso.
Appena c’è un connessione troviamo Timer2.Stop().
State attenti che anche se si trova all’inizio le istruzioni dopo vengono comunque eseguite. L’unica differenza è che al termine delle istruzioni il Timer non ripartirà.
Con questo codice abbiamo anche fatto partire il Timer1. Andiamo adesso a programmare il suo evento Tick (Timer1.Tick), e inseriamo:
Codice:
[COLOR=blue][FONT=Consolas] If[/FONT][/COLOR][FONT=Consolas] cliente.Available > 0 [COLOR=blue]Then[/COLOR] [COLOR=green]'Se i dati che ricevi da cliente sono disponibili e sono maggiori di 0[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp(cliente.Available - 1) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] [COLOR=green]'Dichiaro un array con dimensioni uguali al numero di dati ricevuti da cliente meno 1[/COLOR][/FONT]
[FONT=Consolas] flusso.Read(temp, 0, temp.Length) [COLOR=green]'Leggo il flusso di dati[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] testo [COLOR=blue]As[/COLOR] [COLOR=blue]String[/COLOR] = UTF8.GetString(temp) [COLOR=green]'Decodifica temp in stringa UTF8 e mettila in testo[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Client: "[/COLOR] & testo & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
Dim temp(cliente.Available – 1) As Byte significa che l’array temp è di tipo byte ed è di dimensioni uguali al numero di informazioni che devo ricevere dal client meno 1.
flusso.Read(temp, 0, temp.Length) significa: leggi il byte del flusso dalla posizione zero (dall’inizio) fino alla lunghezza di temp (ovvero fino alla fine del numero di byte da ricevere) e scrivi queste informazioni in temp.
A questo punto temp conterrà le informazioni che ci ha inviato il client in forma di bytes.
Dim testo As String = UTF8.GetString(temp) con questa riga ho convertito tutti i bytes di temp in UTF8 e ho messo questa stringa dentro alla variabile testo.
Questo testo verrà poi scritto nella TextBox2.
Possiamo anche poi aggiungere, sotto al codice scritto prima (sotto End If), queste righe:
Codice:
[COLOR=blue][FONT=Consolas] If[/FONT][/COLOR][FONT=Consolas] testo = [COLOR=#a31515]"start music"[/COLOR] [COLOR=blue]Then[/COLOR] [COLOR=green]'Se testo è uguale a musica1 allora...[/COLOR][/FONT]
[FONT=Consolas] AxWindowsMediaPlayer1.URL = System.[COLOR=#2b91af]Environment[/COLOR].GetFolderPath([COLOR=#2b91af]Environment[/COLOR].[COLOR=#2b91af]SpecialFolder[/COLOR].DesktopDirectory) + [COLOR=#a31515]"/song.mp3"[/COLOR] [COLOR=green]'Avvia song.mp3 in AxWindowsMediaPlayer1[/COLOR][/FONT]
[FONT=Consolas] AxWindowsMediaPlayer1.Ctlcontrols.play() [COLOR=green]'Premi play[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]ElseIf[/COLOR] testo = [COLOR=#a31515]"stop music"[/COLOR] [COLOR=blue]Then[/COLOR] [COLOR=green]'Altrimenti se il testo è stop allora...[/COLOR][/FONT]
[FONT=Consolas] AxWindowsMediaPlayer1.Ctlcontrols.stop() [COLOR=green]'Premi stop[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
E questa riga che fa?!?È più semplice di quanto sembra. Inserisce come canzone da riprodurre nel controllo WindowsMediaPlayer il file song.mp3 contenuto nel Desktop.
Infatti System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) è la directory (il percorso) del Desktop, in qualsiasi computer.
Se voi cambiate l’ultima parte (DesktopDirectory) potete scegliere altri percorsi, validi in tutti i computer, anche se le cartelle hanno nomi diversi.
AxWindowsMediaPlayer1.Ctlcontrols.play() avvia la musica, e con stop() viene fermata.
In sostanza il codice sopra significa:
Se il client ha inviato “start music” allora fai partire la musica (file song.mp3 che è nel desktop).
Se ha invece inviato “stop music” allora ferma la riproduzione.
Adesso ci manca da programmare l’evento Click del Button1 (Button1.Click), il tasto per inviare informazioni al client: al suo interno scriviamo:
Codice:
[FONT=Consolas]TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Server: "[/COLOR] & TextBox1.Text & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Dim[/FONT][/COLOR][FONT=Consolas] temp() [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] = UTF8.GetBytes(TextBox1.Text) [COLOR=green]'Decodifica la stringa in TextBox1 in bytes e metti ogni byte nell'array temp[/COLOR][/FONT]
[FONT=Consolas] flusso.Write(temp, 0, temp.Length) [COLOR=green]'Scrivi il flusso di dati[/COLOR][/FONT]
[FONT=Consolas] TextBox1.Text = [COLOR=#a31515]""[/COLOR] [COLOR=green]'Cancello testo[/COLOR][/FONT]
Il risultato finale dovrebbe essere questo:
Codice:
[COLOR=blue][FONT=Consolas] Imports[/FONT][/COLOR][FONT=Consolas] System.Net.Sockets [COLOR=green]'Libreria per gestire i sockets[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Text.[COLOR=#2b91af]UTF8Encoding[/COLOR] [COLOR=green]'Libreria per decodificare in UTF8[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Public[/FONT][/COLOR][FONT=Consolas] [COLOR=blue]Class[/COLOR] [COLOR=#2b91af]Form1[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] servitore [COLOR=blue]As[/COLOR] [COLOR=#2b91af]TcpListener[/COLOR] [COLOR=green]'Variabile server[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] cliente [COLOR=blue]As[/COLOR] [COLOR=#2b91af]TcpClient[/COLOR] [COLOR=green]'Variabile client[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] flusso [COLOR=blue]As[/COLOR] [COLOR=#2b91af]NetworkStream[/COLOR] [COLOR=green]'Variabile flusso di dati client-server[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Form1_Load([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] [COLOR=blue]MyBase[/COLOR].Load[/FONT]
[FONT=Consolas] servitore = [COLOR=blue]New[/COLOR] [COLOR=#2b91af]TcpListener[/COLOR](8888) [COLOR=green]'servitore è un nuovo server che riceve/invia dati su porta 8888[/COLOR][/FONT]
[FONT=Consolas] servitore.Start() [COLOR=green]'Avvio server[/COLOR][/FONT]
[FONT=Consolas] Timer2.Start() [COLOR=green]'Avvio Timer2[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Server avviato!"[/COLOR] & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Timer2_Tick([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Timer2.Tick[/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] servitore.Pending() [COLOR=blue]Then[/COLOR] [COLOR=green]'Se ci sono richieste di connessione in sospeso allora...[/COLOR][/FONT]
[FONT=Consolas] Timer2.Stop() [COLOR=green]'Stop Timer2[/COLOR][/FONT]
[FONT=Consolas] cliente = servitore.AcceptTcpClient() [COLOR=green]'Accetta la connessione in sospeso[/COLOR][/FONT]
[FONT=Consolas] flusso = cliente.GetStream()[COLOR=green]'Flusso è l’invio/ricezione (Stream) di dati con cliente[/COLOR][/FONT]
[FONT=Consolas] Timer1.Start() [COLOR=green]'Avvia Timer1[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Si è connesso un utente in data "[/COLOR] & Now() & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Timer1_Tick([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Timer1.Tick[/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] cliente.Available > 0 [COLOR=blue]Then[/COLOR] [COLOR=green]'Se i dati che ricevi da cliente sono disponibili e sono maggiori di 0[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp(cliente.Available - 1) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] [COLOR=green]'Dichiaro un array con dimensioni uguali al numero di dati ricevuti da cliente meno 1[/COLOR][/FONT]
[FONT=Consolas] flusso.Read(temp, 0, temp.Length) [COLOR=green]'Leggo il flusso di dati[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] testo [COLOR=blue]As[/COLOR] [COLOR=blue]String[/COLOR] = UTF8.GetString(temp) [COLOR=green]'Decodifica temp in stringa UTF8 e mettila in testo[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Client: "[/COLOR] & testo & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] testo = [COLOR=#a31515]"start music"[/COLOR] [COLOR=blue]Then[/COLOR] [COLOR=green]'Se testo è uguale a musica1 allora...[/COLOR][/FONT]
[FONT=Consolas] AxWindowsMediaPlayer1.URL = System.[COLOR=#2b91af]Environment[/COLOR].GetFolderPath([COLOR=#2b91af]Environment[/COLOR].[COLOR=#2b91af]SpecialFolder[/COLOR].DesktopDirectory) + [COLOR=#a31515]"/song.mp3"[/COLOR] [COLOR=green]'Avvia song.mp3 in AxWindowsMediaPlayer1[/COLOR][/FONT]
[FONT=Consolas] AxWindowsMediaPlayer1.Ctlcontrols.play() [COLOR=green]'Premi play[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]ElseIf[/COLOR] testo = [COLOR=#a31515]"stop music"[/COLOR] [COLOR=blue]Then[/COLOR] [COLOR=green]'Altrimenti se il testo è stop allora...[/COLOR][/FONT]
[FONT=Consolas] AxWindowsMediaPlayer1.Ctlcontrols.stop() [COLOR=green]'Premi stop[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Button1_Click([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Button1.Click[/FONT]
[FONT=Consolas]TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Server: "[/COLOR] & TextBox1.Text & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp() [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] = UTF8.GetBytes(TextBox1.Text) [COLOR=green]'Decodifica la stringa in TextBox1 in bytes e metti ogni byte nell'array temp[/COLOR][/FONT]
[FONT=Consolas] flusso.Write(temp, 0, temp.Length) [COLOR=green]'Scrivi il flusso di dati[/COLOR][/FONT]
[FONT=Consolas] TextBox1.Text = [COLOR=#a31515]""[/COLOR] [COLOR=green]'Cancello testo[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]End[/FONT][/COLOR][FONT=Consolas] [COLOR=blue]Class[/COLOR][/FONT]
Creazione del Client
Creiamo un nuovo progetto, scegliamo come modello Applicazione Windows Form, e chiamiamolo Client.
Nel nostro Form inseriamo una TextBox (nome: TextBox1) e accanto mettiamo un Button (nome: Button1; Proprietà Text: “CONNETTI”).
Sempre vicino a questo button mettiamo una CheckBox (nome: CheckBox1; Proprietà Text: “HostName?”).
Un po’ più un basso mettiamo un’altra TextBox (nome: TextBox2), accanto a questa un altro Button (nome: Button2; Proprietà Text: “INVIA”), e subito sotto un’altra TextBox (nome: TextBox3; Proprietà Multiline: True).
Mettiamo anche un Timer (nome: Timer1).
Importiamo le stesse librerie che avevamo importato anche nel server:
Codice:
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Net.Sockets [COLOR=green]'Libreria per gestire i sockets[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Text.[COLOR=#2b91af]UTF8Encoding[/COLOR] [COLOR=green]'Libreria per decodificare in UTF8[/COLOR][/FONT]
Codice:
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] cliente [COLOR=blue]As[/COLOR] [COLOR=#2b91af]TcpClient[/COLOR] [COLOR=green]'Variabile client[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] flusso [COLOR=blue]As[/COLOR] [COLOR=#2b91af]NetworkStream[/COLOR] [COLOR=green]'Variabile flusso di dati client-server[/COLOR][/FONT]
Adesso andiamo a programmare l’evento Click del Button1 (Button1.Click):
Codice:
[COLOR=blue][FONT=Consolas] Dim[/FONT][/COLOR][FONT=Consolas] AddressIP [COLOR=blue]As[/COLOR] [COLOR=blue]String[/COLOR] = TextBox1.Text [COLOR=green]'Metto l'ip dentro ad AddressIP[/COLOR][/FONT]
[FONT=Consolas] [COLOR=green]'PRENDO IP DELL'HOST SE QUELLO INSERITO è UN HOSTNAME E LO METTO DENTRO AD AddressIP[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] CheckBox1.Checked = [COLOR=blue]True[/COLOR] [COLOR=blue]Then[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] IpCollection [COLOR=blue]As[/COLOR] [COLOR=blue]New[/COLOR] [COLOR=#2b91af]Collection[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] ipE [COLOR=blue]As[/COLOR] Net.[COLOR=#2b91af]IPHostEntry[/COLOR] = System.Net.[COLOR=#2b91af]Dns[/COLOR].GetHostEntry(TextBox1.Text)[/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] IpA() [COLOR=blue]As[/COLOR] Net.[COLOR=#2b91af]IPAddress[/COLOR] = ipE.AddressList[/FONT]
[FONT=Consolas] [COLOR=blue]For[/COLOR] i = 0 [COLOR=blue]To[/COLOR] IpA.GetUpperBound(0)[/FONT]
[FONT=Consolas] IpCollection.Add(IpA(i).ToString)[/FONT]
[FONT=Consolas] [COLOR=blue]Next[/COLOR][/FONT]
[FONT=Consolas] AddressIP = IpCollection.Item(1)[/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR][/FONT]
[FONT=Consolas] cliente = [COLOR=blue]New[/COLOR] [COLOR=#2b91af]TcpClient[/COLOR] [COLOR=green]'cliente è un nuovo client[/COLOR][/FONT]
[FONT=Consolas] cliente.Connect(AddressIP, 8888) [COLOR=green]'Connetti cliente all'indirizzo ip indirizzo attraverso la porta 8888[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] cliente.Connected [COLOR=blue]Then[/COLOR] [COLOR=green]'Se cliente è connesso allora... (cioè se il server è in ascolto)[/COLOR][/FONT]
[FONT=Consolas] TextBox3.Text = TextBox3.Text & [COLOR=#a31515]"Connesso!"[/COLOR] & vbCrLf [COLOR=green]'Scrivo in TextBox3[/COLOR][/FONT]
[FONT=Consolas] flusso = cliente.GetStream() [COLOR=green]'flusso è l’invio/ricezione (Stream) di dati con il server al quale cliente è connesso[/COLOR][/FONT]
[FONT=Consolas] Timer1.Start() [COLOR=green]'Avvio Timer1[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Else[/COLOR] [COLOR=green]'Altrimenti...[/COLOR][/FONT]
[FONT=Consolas] TextBox3.Text = TextBox3.Text & [COLOR=#a31515]"Il server non risponde!"[/COLOR] & vbCrLf [COLOR=green]'Scrivo in TextBox3[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
Poi viene però effettuato un controllo: se la CheckBox1 è spuntata allora esegue una lunga serie di istruzioni e poi inserisce un altro valore in AddressIP.
In questo If viene preso l’indirizzo IP di un HostName e viene messo in AddressIP.
Un HostName è un nome che “sostitusce” l’indirizzo IP.
Un esempio è google.it (senza http://www.). Quando voi inserite google.it nel vostro browser verrete indirizzati alla home di google.
Ma provate ora a scrivere nelle barra degli indirizzi del vostro browser 209.85.147.103, e vedete che verrete indirizzati di nuovo a google, infatti 209.85.147.103 è l’indirizzo IP del server di google.
Per ricavare l’indirizzo IP di un Host potete aprire il prompt dei comandi di windows (Start --> Esegui… --> cmd.exe) e digitare ping google.it
Quello che compare tra le parentesi tonde è l’IP del server (in questo caso del server di google).
Quindi se la CheckBox1 è spuntata il nostro programma prende l’IP dell’HostName inserito invece di considerare quello che è stato scritto come indirizzo IP.
cliente.Connect(AddressIP, 8888) Con questa riga il client si connette al server che ha l’IP che è contenuto in AddressIP attraverso la porta 8888.
Dopo esegue un controllo e se è connesso chiama flusso il flusso di dati client-server (come nel server) e scrive nella TextBox3 che è connesso. Altrimenti scrive nella TextBox3 che il server non risponde.
Con questo abbiamo anche avviato il Timer1. Andiamo a programmare il suo evento Tick (Timer1.Tick):
Codice:
[FONT=Consolas] [COLOR=blue]If[/COLOR] cliente.Available > 0 [COLOR=blue]Then[/COLOR] [COLOR=green]'Se i dati che ricevi dal server al quale è connesso cliente sono disponibili e sono maggiori di 0[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp(cliente.Available - 1) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] [COLOR=green]'Dichiaro un array con dimensioni uguali al numero di dati ricevuti da cliente meno 1[/COLOR][/FONT]
[FONT=Consolas] flusso.Read(temp, 0, temp.Length) [COLOR=green]'Leggo il flusso di dati[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] testo [COLOR=blue]As[/COLOR] [COLOR=blue]String[/COLOR] = UTF8.GetString(temp) [COLOR=green]'Decodifica temp in stringa UTF8 e mettila in testo[/COLOR][/FONT]
[FONT=Consolas] TextBox3.Text = TextBox3.Text & [COLOR=#a31515]"Server: "[/COLOR] & testo & vbCrLf [COLOR=green]'Scrivo nella TextBox3[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
Adesso andiamo a programmare l’evento Click del Button2 (Button2.Click):
Codice:
[FONT=Consolas] TextBox3.Text = TextBox3.Text & [COLOR=#a31515]"Client: "[/COLOR] & TextBox2.Text & vbCrLf [COLOR=green]'Scrivo nella TextBox3[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Dim[/FONT][/COLOR][FONT=Consolas] temp() [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] = UTF8.GetBytes(TextBox2.Text) [COLOR=green]'Decodifica la stringa in TextBox2 in bytes e metti ogni byte nell'array temp[/COLOR][/FONT]
[FONT=Consolas] flusso.Write(temp, 0, temp.Length) [COLOR=green]'Scrivi il flusso di dati[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = [COLOR=#a31515]""[/COLOR] [COLOR=green]'Cancello testo[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Focus() [COLOR=green]'Attivo TextBox2[/COLOR][/FONT]
Bene… Il risultato finale dovrebbe essere questo:
Codice:
[COLOR=blue][FONT=Consolas] Imports[/FONT][/COLOR][FONT=Consolas] System.Net.Sockets [COLOR=green]'Libreria per gestire i sockets[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Text.[COLOR=#2b91af]UTF8Encoding[/COLOR] [COLOR=green]'Libreria per decodificare in UTF8[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Public[/FONT][/COLOR][FONT=Consolas] [COLOR=blue]Class[/COLOR] [COLOR=#2b91af]Form1[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] cliente [COLOR=blue]As[/COLOR] [COLOR=#2b91af]TcpClient[/COLOR] [COLOR=green]'Variabile client[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] flusso [COLOR=blue]As[/COLOR] [COLOR=#2b91af]NetworkStream[/COLOR] [COLOR=green]'Variabile flusso di dati client-server[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Button1_Click([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Button1.Click[/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] AddressIP [COLOR=blue]As[/COLOR] [COLOR=blue]String[/COLOR] = TextBox1.Text [COLOR=green]'Metto l'ip dentro ad AddressIP[/COLOR][/FONT]
[FONT=Consolas] [COLOR=green]'PRENDO IP DELL'HOST SE QUELLO INSERITO è UN HOSTNAME E LO METTO DENTRO AD AddressIP[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] CheckBox1.Checked = [COLOR=blue]True[/COLOR] [COLOR=blue]Then[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] IpCollection [COLOR=blue]As[/COLOR] [COLOR=blue]New[/COLOR] [COLOR=#2b91af]Collection[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] ipE [COLOR=blue]As[/COLOR] Net.[COLOR=#2b91af]IPHostEntry[/COLOR] = System.Net.[COLOR=#2b91af]Dns[/COLOR].GetHostEntry(TextBox1.Text)[/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] IpA() [COLOR=blue]As[/COLOR] Net.[COLOR=#2b91af]IPAddress[/COLOR] = ipE.AddressList[/FONT]
[FONT=Consolas] [COLOR=blue]For[/COLOR] i = 0 [COLOR=blue]To[/COLOR] IpA.GetUpperBound(0)[/FONT]
[FONT=Consolas] IpCollection.Add(IpA(i).ToString)[/FONT]
[FONT=Consolas] [COLOR=blue]Next[/COLOR][/FONT]
[FONT=Consolas] AddressIP = IpCollection.Item(1)[/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR][/FONT]
[FONT=Consolas] cliente = [COLOR=blue]New[/COLOR] [COLOR=#2b91af]TcpClient[/COLOR] [COLOR=green]'cliente è un nuovo client[/COLOR][/FONT]
[FONT=Consolas] cliente.Connect(AddressIP, 8888) [COLOR=green]'Connetti cliente all'indirizzo ip indirizzo attraverso la porta 8888[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] cliente.Connected [COLOR=blue]Then[/COLOR] [COLOR=green]'Se cliente è connesso allora... (cioè se il server è in ascolto)[/COLOR][/FONT]
[FONT=Consolas] TextBox3.Text = TextBox3.Text & [COLOR=#a31515]"Connesso!"[/COLOR] & vbCrLf [COLOR=green]'Scrivo in TextBox3[/COLOR][/FONT]
[FONT=Consolas] flusso = cliente.GetStream() [COLOR=green]'flusso è l’invio/ricezione (Stream) di dati con il server al quale cliente è connesso[/COLOR][/FONT]
[FONT=Consolas] Timer1.Start() [COLOR=green]'Avvio Timer1[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Else[/COLOR] [COLOR=green]'Altrimenti...[/COLOR][/FONT]
[FONT=Consolas] TextBox3.Text = TextBox3.Text & [COLOR=#a31515]"Il server non risponde!"[/COLOR] & vbCrLf [COLOR=green]'Scrivo in TextBox3[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Timer1_Tick([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Timer1.Tick[/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] cliente.Available > 0 [COLOR=blue]Then[/COLOR] [COLOR=green]'Se i dati che ricevi dal server al quale è connesso cliente sono disponibili e sono maggiori di 0[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp(cliente.Available - 1) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] [COLOR=green]'Dichiaro un array con dimensioni uguali al numero di dati ricevuti da cliente meno 1[/COLOR][/FONT]
[FONT=Consolas] flusso.Read(temp, 0, temp.Length) [COLOR=green]'Leggo il flusso di dati[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] testo [COLOR=blue]As[/COLOR] [COLOR=blue]String[/COLOR] = UTF8.GetString(temp) [COLOR=green]'Decodifica temp in stringa UTF8 e mettila in testo[/COLOR][/FONT]
[FONT=Consolas] TextBox3.Text = TextBox3.Text & [COLOR=#a31515]"Server: "[/COLOR] & testo & vbCrLf [COLOR=green]'Scrivo nella TextBox3[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Button2_Click([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2b91af]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Button2.Click[/FONT]
[FONT=Consolas] TextBox3.Text = TextBox3.Text & [COLOR=#a31515]"Client: "[/COLOR] & TextBox2.Text & vbCrLf [COLOR=green]'Scrivo nella TextBox3[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp() [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] = UTF8.GetBytes(TextBox2.Text) [COLOR=green]'Decodifica la stringa in TextBox2 in bytes e metti ogni byte nell'array temp[/COLOR][/FONT]
[FONT=Consolas] flusso.Write(temp, 0, temp.Length) [COLOR=green]'Scrivi il flusso di dati[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = [COLOR=#a31515]""[/COLOR] [COLOR=green]'Cancello testo[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Focus() [COLOR=green]'Attivo TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]End[/FONT][/COLOR][FONT=Consolas] [COLOR=blue]Class[/COLOR][/FONT]
Ci sono tre diversi tipi di connessione:
Connessione su stesso computer: La connessione tra il client e il server viene effettuata sullo stesso computer. Adatto se si vuole vedere il funzionamento del programma.
Connessione su due computer nella rete locale: La connessione tra il client e il server viene effettuata su due computer differenti, ma questi computer sono connessi alla stessa rete (di solito mediante un router). Adatto se si vuole vedere il funzionamento del programma e si hanno a disposizione due computer è un router.
Connessione remota su due computer: La connessione tra il client e il server viene effettuata su due computer differenti che sono connessi ad internet e si possono trovare in qualsiasi parte del pianeta. Adatto se si vuole far connettere due computer distanti.
Una cosa che mi sono scordato di farvi notare è che la connessione viene effettuata attraverso la porta 8888. Questa porta, se si vuole cambiarla, deve essere cambiata sia nel client che nel server.
Connessione su stesso computer
Avviamo sia il nostro server che il client (prima compilateli, o eseguiteli tutti e due all’interno del debugger di Visual Studio).
Se tutto va bene nel server dovrebbe comparire la scritta “Server avviato!”.
N.B.: è possibile che il vostro firewall blocchi la connessione. Se è così dovrete sbloccarla o disattivare il firewall.
Nella TextBox1 del client mettiamo 127.0.0.1
127.0.0.1 è l’IP del computer stesso. Un computer per indicare se stesso usa sempre 127.0.0.1. Diciamo così al nostro client di connettere a questo stesso computer.
Adesso clicchiamo su connetti.
Se tutto va bene sia il client che il server dovrebbero segnalare che si sono connessi.
Adesso potete scrivere messaggi dal server al client e viceversa. Inoltre se dal client inviate “start music” il server farà partire la musica che avete scelto, se scrivete invece “stop music” la fermerà.
Connessione su 2 computer nella rete locale
Avviate su un computer il client e sull’altro il server.
Adesso nel computer dove avete avviato il server aprite il prompt dei comandi di windows e scrivete ipconfig
Visualizzerete una lunga serie di scritte che per molto di voi saranno anche incomprensibili.
Dovreste però trovare scritto da qualche parte una cosa tipo:
Indirizzo IPv4 oppure Indirizzo IP e accanto trovate scritto l’IP della rete locale.
L’IP della rete locale comincia sempre con 192.168 e poi ci sono 2 numeri che variano da computer a computer, da rete a rete.
Nella TextBox1 del client mettiamo quell’IP e clicchiamo su connetti.
Se tutto va bene sia il client che il server dovrebbero segnalare che si sono connessi.
Adesso potete scrivere messaggi dal server al client e viceversa. Inoltre se dal client inviate “start music” il server farà partire la musica che avete scelto, se scrivete invece “stop music” la fermerà.
Connessione remota su due computer
Dobbiamo prima avere un indirizzo IP statico per poterlo fare. Per avere un Indirizzo IP statico ci sono due modi:
-Contattare il proprio provider e chiedere che ci venga assegnato un indirizzo IP statico (è necessario un pagamento).
-Utilizzare un comodo servizio chiamato DynDNS (completamente gratuito).
Ovviamente io vi spiegherò il secondo metodo ;-).
Aprite il vostro browser, andate su http://www.dyndns.com e registratevi (Sign In --> Create an Account).
Quando vi siete registrati, andate su My Account o My Services e cercate Add Host Services (dovrebbe essere nella scheda My Services).
Cliccate su quel link e nella pagina che vi verrà mostrata inserite come HostName quello che preferite, come Service Type mettete Host with IP address e come IP Address mettete quello che leggete subito sotto (vi basta cliccare su quel link per inserirlo automaticamente).
Adesso cliccate su Add To Cart (tranquilli tutto gratuito) e poi su Next.
A questo punto avete aggiunto al vostro ip un HostName. Ma il vostro IP non è ancora “statico”.
Esattamente quello che faremo non è rendere il vostro IP statico ma far si che anche se il vostro IP è dinamico (cioè cambia in continuazione) attraverso l’HostName potrete sempre connettere all’IP, qualunque esso sia.
Per fare ciò dobbiamo scaricare un programma che si chiama DynDNS Updater.
Per scaricarlo cliccate su Support e poi su Download Now (oppure direttamente da QUI ).
Appena scaricato spuntate la casella del vostro HostName che avete appena creato e poi su Apply.
Adesso potete anche minimizzare l’applicazione che continuerà ad aggiornare l’Host con il vostro nuovo IP ogni volta che cambia.
Non è ancora finita. Per far si che il server e il client possano comunicare deve essere aperta la porta 8888 (quella che abbiamo scelto per farli connettere, potete cambiarla con un'altra qualsiasi se volete).
Di solito non è necessario aprirla anche nel client, ma se non funzionasse provate ad aprirla anche nel computer dove è situato il client.
Comunque per aprirla (sia che sia il computer con il server che quello con il client) dovrete aprire il vostro browser e digitare nella barra degli indirizzi il vostro HostName che prima avete creato (se non funzionasse potete inserire l’indirizzo del vostro Gateway (Gateway predefinito), che visualizzate scrivendo ipconfig nel prompt dei comandi di windows).
Accedete al pannello di controllo (spesso l’id e la password sono admin e admin, ma comunque vi deve essere stata fornita quando avete comprato il vostro modem/router) e cercate il punto dove potete aprire le vostre porte (non è sempre così facile trovarlo, io l’ho ad esempio in Avanzate --> Inoltro delle porte).
Di solito chiedono:
Nome applicazione: Inserite quello che volete, ad esempio ProvaConnessione.
Indirizzo IP: Inserite l’indirizzo IP del vostro computer sulla rete locale (quello che inizia con 192.168; attenzione: non dovete inserire quello del Gateway).
TCP(Porta Esterna): mettete 8888
UDP(Porta Esterna): 8888
TCP(Porta Enterna): 8888
UDP(Porta Enterna): 8888
Al termine salvate le modifiche (a volte è anche necessario riavviare il modem/router).
Una comoda alternativa è di utilizzare una piccola utility chiamata PortMap. Potete scaricarla da qui:
MEGAUPLOAD - The leading online storage and file delivery service
Scansione VirusTotal[8/41]:
VirusTotal - Free Online Virus, Malware and URL Scanner
Essendo un programma che apre delle porte, molti antivirus lo rilevano come virus.
All'interno del file rar troverete 2 file: un txt che è il file di configurazione; un eseguibile che all'avvio dovrebbe aprire le porte come impostato nel file di configurazione.
Dovrete cambiare l'outerIP e cose varie.
Ometto la spiegazione dettagliata su come utilizzare PortMap.
Adesso che abbiamo aperto anche la porta non ci basta che avviare il client e il server e provare.
Nella TextBox1 del client mettete l’HostName che avete scelto prima, spuntate la CheckBox, e poi cliccate su connetti.
Se tutto va bene sia il client che il server dovrebbero segnalare che si sono connessi.
Adesso potete scrivere messaggi dal server al client e viceversa. Inoltre se dal client inviate “start music” il server farà partire la musica che avete scelto, se scrivete invece “stop music” la fermerà.
Importanti informazioni su DynDNS
Spesso potrebbe verificarsi che, dopo aver aperto l'host su DynDNS, se cercate di aprire determinate pagine web potreste non visualizzarla perchè DynDNS vi impedisce di aprire quella pagina.
è possibile ovviamente risolvere questo problema ma.... se lo fate i client non potranno più connettere al vostro server e voi perderete il vostro "ip statico" (ma non per sempre, potete rimetterlo quando volete, ma se lo rimettete quelle pagine torneranno a essere bloccate).
Per risolverlo dovrete:
1- Chiudere DynDNS Updater.
2- Andare in Pannello di controllo --> Centro connessioni di rete e condivisione --> Modifica impostazioni scheda --> cliccate con il destro sulla vostra scheda di rete e premete su Proprietà --> Selezionate Protocollo Internet versione 4 (TCP/IPv4) --> Togliete i due server DNS e sostituiteli con altri (magari inserite Ottieni indirizzi server DNS automaticamente).
Modificare il server per la multiconnessione
Abbiamo fino ad ora imparato come connettere un client ad un server.
Ma i veri server (game server, server di messaggistica istantanea (Skype, MSN, ecc.), server di siti web, ecc.) funzionano diversamente:
Invece di far connettere un solo client, fanno connettere più client. Ci sono 2 modalità di connessione (o meglio modalità di scambio di informazioni):
Nella prima, i vari client connettono al server che scambia informazioni con questi mantenendo “autonomo” il contatto con ognuno di loro.
Ovvero i client connettono al server, inviano, ma più spesso, scaricano informazioni dal server e tutto finisce qui. Le informazioni che circolano ad esempio tra il client A e il server sono completamente separate da quelle che circolano tra il client B e il server.
Nella seconda, invece, i vari client connettono al server, e poi attraverso quest’ultimo, scambiano informazioni tra di loro (è il funzionamento dei server di messaggistica istantanea, o, se vogliamo, anche dei server mail, quelli che gestiscono la posta elettronica).
Le informazioni che partono dal client A, arrivano al server che le invia al client B.
In questa parte della guida impareremo proprio a creare un sistema di messaggistica istantanea (se imparerete bene a fare questo, non avrete difficoltà a modificare il codice come meglio serve a voi, e magari anche a trasformarlo nella prima modalità se vi è necessario).
Per fare ciò ci basterà andare a modificare alcune parti del server (il client funziona benissimo così).
In particolare dovremo semplicemente trasformare la variabile cliente in un array così che possa contenere più client invece che uno solo, poi dovremo modificare il sistema di ricezione e invio delle informazioni.
Per fare ciò direi di riprendere da zero la creazione del server.
Al termine del lavoro sarà possibile:
-Inviare informazioni tra un client e l’altro attraverso il server, e il server inoltre potrà inviare informazioni a tutti i client quando lo vorrà il proprietario.
Allora, mettiamo al lavoro.
Mi scuso se il codice non funziona ma non l’ho testato e inoltre l’ho scritto direttamente sul web. Ho comunque ricontrollato il codice è sembra essere corretto. In caso di problemi vi prego di segnalarli.
Creiamo un nuovo progetto, scegliamo come modello Applicazione Windows Form e come nome mettiamo MultiConnectionServer.
Inseriamo gli stessi controlli che avevamo inserito nel vecchio server tranne il controllo WindowsMediaPlayer (tanto ormai avete capito come funziona).
I controlli, con le rispettive proprietà da modificare, erano:
-TextBox1
-Button1 --> Proprietà Text: “INVIA”
-TextBox2 --> Proprietà Multiline: True (allungate poi la TextBox verso il basso).
-Timer1 e Timer2
Adesso importiamo di nuovo le solite librerie:
Codice:
[COLOR=blue][FONT=Consolas] Imports[/FONT][/COLOR][FONT=Consolas] System.Net.Sockets [COLOR=green]'Libreria per gestire i sockets[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Text.[COLOR=#2b91af]UTF8Encoding[/COLOR] [COLOR=green]'Libreria per codificare in UTF8[/COLOR][/FONT]
Codice:
[COLOR=blue][FONT=Consolas] Dim[/FONT][/COLOR][FONT=Consolas] servitore [COLOR=blue]As[/COLOR] [COLOR=#2b91af]TcpListener[/COLOR] [COLOR=green]'Variabile server[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] cliente(-1) [COLOR=blue]As[/COLOR] [COLOR=#2b91af]TcpClient[/COLOR] [COLOR=green]'Array client[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] flusso(-1) [COLOR=blue]As[/COLOR] [COLOR=#2b91af]NetworkStream[/COLOR] [COLOR=green]'Array flusso di dati client-server[/COLOR][/FONT]
Adesso andiamo a programmare l’evento Load del Form (Form1.Load). Il codice sarà uguale a quello del server normale, ovvero:
Codice:
[FONT=Consolas] servitore = [COLOR=blue]New[/COLOR] [COLOR=#2b91af]TcpListener[/COLOR](8888) [COLOR=green]'servitore è un nuovo server che riceve/invia dati su porta 8888[/COLOR][/FONT]
[FONT=Consolas] servitore.Start() [COLOR=green]'Avvio server[/COLOR][/FONT]
[FONT=Consolas] Timer2.Start() [COLOR=green]'Avvio Timer2[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Server avviato!"[/COLOR] & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
Codice:
[FONT=Consolas] [COLOR=blue]If[/COLOR] servitore.Pending() [COLOR=blue]Then[/COLOR] [COLOR=green]'Se ci sono richieste di connessione in sospeso allora...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=#2b91af]Array[/COLOR].Resize(cliente, cliente.Length + 1) [COLOR=green]'Aggiungi 1 alla dimesione dell'array cliente[/COLOR][/FONT]
[FONT=Consolas] cliente(cliente.Length - 1) = servitore.AcceptTcpClient() [COLOR=green]'Accetta la connessione in sospeso nell'ultimo spazio (quello appena creato) dell'array[/COLOR][/FONT]
[FONT=Consolas] [COLOR=#2b91af]Array[/COLOR].Resize(flusso, flusso.Length + 1) [COLOR=green]'Aggiungi 1 alla dimensione dell'array flusso[/COLOR][/FONT]
[FONT=Consolas] flusso(flusso.Length - 1) = cliente(cliente.Length - 1).GetStream() [COLOR=green]'l'ultimo spazio dell'array flusso (quello appena creato) è l'invio/ricezione (Stream) di dati con l'ultimo client che si è connesso (quello di cui abbiamo appena accettato la connessione)[/COLOR][/FONT]
[FONT=Consolas] Timer1.Start() [COLOR=green]'Avvia Timer1[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Si è connesso un utente in data "[/COLOR] & Now() & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
Con Array.Resize ridimensiono sia l’array cliente che l’array flusso aggiungendo uno. Ora dovreste capire perché ho messo -1 come dimensione inziale. Perché il primo client che si connette andrà a piazzarsi della posizione 0 dell’array. Se avessi messo 0 come dimensione iniziale allora il primo client si sarebbe piazzato alla posizione 1, lasciando vuota la posizione 0, che avrebbe poi potuto generare un’eccezione (in particolare: NullReferenceException) se avessimo cercati di richiamare cliente(0).
La stessa cosa vale per l’array flusso.
Per il resto è tutto uguale al server a connessione singola.
Adesso andiamo all’evento Tick del Timer1 (Timer1.Tick).
Qui dovremmo far si che ogni dato che viene ricevuto dal server, venga rinviato da quest’ultimo a tutti i client connessi (quelli che sono all’interno dell’array cliente). Ecco il codice:
Codice:
[FONT=Consolas] [COLOR=blue]For[/COLOR] r = 0 [COLOR=blue]To[/COLOR] UBound(cliente) [COLOR=green]'Per ogni client connesso (contenuto in cliente)...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] cliente(r).Available > 0 [COLOR=blue]Then[/COLOR] [COLOR=green]'Se i dati che ricevi dal cliente che stai controllando (cliente(r)) sono maggiori di 0 e sono disponibili per la lettura allora...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp(cliente(r).Available - 1) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] [COLOR=green]'Dichiaro un array con dimensioni uguali al numero di dati ricevuti da cliente(r) meno 1[/COLOR][/FONT]
[FONT=Consolas] flusso(r).Read(temp, 0, temp.Length) [COLOR=green]'Leggo il flusso di dati (flusso(r)) che è il flusso di dati inviato da cliente(r), e metto questi dati dentro all'array temp (byte per byte) per tutta la loro dimensione[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] testo [COLOR=blue]As[/COLOR] [COLOR=blue]String[/COLOR] = UTF8.GetString(temp) [COLOR=green]'Decodifica temp in stringa UTF8 e mettila in testo[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#a31515]"Client("[/COLOR] + r.ToString + [COLOR=#a31515]"): "[/COLOR] & testo & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]For[/COLOR] s = 0 [COLOR=blue]To[/COLOR] UBound(cliente) [COLOR=green]'Per ogni client connesso...[/COLOR][/FONT]
[FONT=Consolas] flusso(s).Write(temp, 0, temp.Length) [COLOR=green]'Scrivo nel flusso di dati (flusso(s)) che è il flusso che arriva a tutti i client. ovvero invio a flusso(0) che è il flusso che arriva a cliente(0). poi flusso(1) che arriva a cliente(1) e così via...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Next[/COLOR] [COLOR=green]'poi[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Next[/COLOR] [COLOR=green]'poi[/COLOR][/FONT]
Se sta inviando informazioni allora si procede, altrimenti viene controllato un altro client.
Se il client che si sta controllando (cliente(r)) sta inviando informazioni, vengono ricevute byte per byte all’interno dell’array temp e vengono scritte nella TextBox2 con il relativo numero del client che ha scritto (“Client(“ + r.ToString + “): “), così il server può visualizzare chi ha inviato il messaggio.
Poi per ogni client connesso i dati ricevuti da cliente(r), che sono stati messi in temp, vengono scritti al client (flusso(s)).
Bene. Dovreste essere in grado di capire
soprattutto chi è più esperto nel gestire gli array (l’unica difficolta di questo codice può essere questa).Adesso programmiamo l’evento Click del Button1 (Button1.Click):
Codice:
[FONT=Consolas] [COLOR=blue]For[/COLOR] r = 0 [COLOR=blue]To[/COLOR] UBound(cliente) [COLOR=green]'Per ogni client connesso...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp() [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] = UTF8.GetBytes(TextBox1.Text) [COLOR=green]'Decodifica la stringa in TextBox1 in bytes e metti ogni byte nell'array temp[/COLOR][/FONT]
[FONT=Consolas] flusso(r).Write(temp, 0, temp.Length) [COLOR=green]'Scrivo nel flusso di dati (flusso(s)) che è il flusso che arriva a tutti i client, ciò che ha inviato il server. ovvero invio a flusso(0) che è il flusso che arriva a cliente(0). poi flusso(1) che arriva a cliente(1) e così via...[/COLOR][/FONT]
[FONT=Consolas] TextBox1.Text = [COLOR=#a31515]""[/COLOR] [COLOR=green]'Cancello testo[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Next[/COLOR] [COLOR=green]'poi[/COLOR][/FONT]

Bene. Abbiamo finito il nostro server. Il risultato finale dovrebbe essere questo:
Codice:
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Net.Sockets [COLOR=green]'Libreria per gestire i sockets[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Imports[/FONT][/COLOR][FONT=Consolas] System.Text.[COLOR=#2B91AF]UTF8Encoding[/COLOR] [COLOR=green]'Libreria per codificare in UTF8[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Public[/FONT][/COLOR][FONT=Consolas] [COLOR=blue]Class[/COLOR] [COLOR=#2B91AF]Form1[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] servitore [COLOR=blue]As[/COLOR] [COLOR=#2B91AF]TcpListener[/COLOR] [COLOR=green]'Variabile server[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] cliente(-1) [COLOR=blue]As[/COLOR] [COLOR=#2B91AF]TcpClient[/COLOR] [COLOR=green]'Array client[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] flusso(-1) [COLOR=blue]As[/COLOR] [COLOR=#2B91AF]NetworkStream[/COLOR] [COLOR=green]'Array flusso di dati client-server[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Form1_Load([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2B91AF]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2B91AF]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] [COLOR=blue]MyBase[/COLOR].Load[/FONT]
[FONT=Consolas]servitore = [COLOR=blue]New[/COLOR] [COLOR=#2B91AF]TcpListener[/COLOR](8888) [COLOR=green]'servitore è un nuovo server che riceve/invia dati su porta 8888[/COLOR][/FONT]
[FONT=Consolas]servitore.Start() [COLOR=green]'Avvio server[/COLOR][/FONT]
[FONT=Consolas] Timer2.Start() [COLOR=green]'Avvio Timer2[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#A31515]"Server avviato!"[/COLOR] & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Timer2_Tick([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2B91AF]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2B91AF]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Timer2.Tick[/FONT]
[COLOR=blue][FONT=Consolas]If[/FONT][/COLOR][FONT=Consolas] servitore.Pending() [COLOR=blue]Then[/COLOR] [COLOR=green]'Se ci sono richieste di connessione in sospeso allora...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=#2B91AF]Array[/COLOR].Resize(cliente, cliente.Length + 1) [COLOR=green]'Aggiungi 1 alla dimesione dell'array cliente[/COLOR][/FONT]
[FONT=Consolas] cliente(cliente.Length - 1) = servitore.AcceptTcpClient() [COLOR=green]'Accetta la connessione in sospeso nell'ultimo spazio (quello appena creato) dell'array[/COLOR][/FONT]
[FONT=Consolas] [COLOR=#2B91AF]Array[/COLOR].Resize(flusso, flusso.Length + 1) [COLOR=green]'Aggiungi 1 alla dimensione dell'array flusso[/COLOR][/FONT]
[FONT=Consolas] flusso(flusso.Length - 1) = cliente(cliente.Length - 1).GetStream() [COLOR=green]'l'ultimo spazio dell'array flusso (quello appena creato) è l'invio/ricezione (Stream) di dati con l'ultimo client che si è connesso (quello di cui abbiamo appena accettato la connessione)[/COLOR][/FONT]
[FONT=Consolas] Timer1.Start() [COLOR=green]'Avvia Timer1[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#A31515]"Si è connesso un utente in data "[/COLOR] & Now() & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]End[/FONT][/COLOR][FONT=Consolas] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Timer1_Tick([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2B91AF]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2B91AF]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Timer1.Tick[/FONT]
[COLOR=blue][FONT=Consolas]For[/FONT][/COLOR][FONT=Consolas] r = 0 [COLOR=blue]To[/COLOR] UBound(cliente) [COLOR=green]'Per ogni client connesso (contenuto in cliente)...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]If[/COLOR] cliente(r).Available > 0 [COLOR=blue]Then[/COLOR] [COLOR=green]'Se i dati che ricevi dal cliente che stai controllando (cliente(r)) sono maggiori di 0 e sono disponibili per la lettura allora...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp(cliente(r).Available - 1) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] [COLOR=green]'Dichiaro un array con dimensioni uguali al numero di dati ricevuti da cliente(r) meno 1[/COLOR][/FONT]
[FONT=Consolas] flusso(r).Read(temp, 0, temp.Length) [COLOR=green]'Leggo il flusso di dati (flusso(r)) che è il flusso di dati inviato da cliente(r), e metto questi dati dentro all'array temp (byte per byte) per tutta la loro dimensione[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] testo [COLOR=blue]As[/COLOR] [COLOR=blue]String[/COLOR] = UTF8.GetString(temp) [COLOR=green]'Decodifica temp in stringa UTF8 e mettila in testo[/COLOR][/FONT]
[FONT=Consolas] TextBox2.Text = TextBox2.Text & [COLOR=#A31515]"Client("[/COLOR] + r.ToString + [COLOR=#A31515]"): "[/COLOR] & testo & vbCrLf [COLOR=green]'Scrivo nella TextBox2[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]For[/FONT][/COLOR][FONT=Consolas] s = 0 [COLOR=blue]To[/COLOR] UBound(cliente) [COLOR=green]'Per ogni client connesso...[/COLOR][/FONT]
[FONT=Consolas]flusso(s).Write(temp, 0, temp.Length) [COLOR=green]'Scrivo nel flusso di dati (flusso(s)) che è il flusso che arriva a tutti i client, ciò che è contenuto in temp. ovvero invio a flusso(0) che è il flusso che arriva a cliente(0). poi flusso(1) che arriva a cliente(1) e così via...[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]Next[/FONT][/COLOR][FONT=Consolas] [COLOR=green]'poi[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]If[/COLOR] [COLOR=green]'Fine se[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Next[/COLOR] [COLOR=green]'poi[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Private[/COLOR] [COLOR=blue]Sub[/COLOR] Button1_Click([COLOR=blue]ByVal[/COLOR] sender [COLOR=blue]As[/COLOR] System.[COLOR=#2B91AF]Object[/COLOR], [COLOR=blue]ByVal[/COLOR] e [COLOR=blue]As[/COLOR] System.[COLOR=#2B91AF]EventArgs[/COLOR]) [COLOR=blue]Handles[/COLOR] Button1.Click[/FONT]
[FONT=Consolas] [COLOR=blue]For[/COLOR] r = 0 [COLOR=blue]To[/COLOR] UBound(cliente) [COLOR=green]'Per ogni client connesso...[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] temp() [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] = UTF8.GetBytes(TextBox1.Text) [COLOR=green]'Decodifica la stringa in TextBox1 in bytes e metti ogni byte nell'array temp[/COLOR][/FONT]
[FONT=Consolas]flusso(r).Write(temp, 0, temp.Length) [COLOR=green]'Scrivo nel flusso di dati (flusso(s)) che è il flusso che arriva a tutti i client, ciò che ha inviato il server. ovvero invio a flusso(0) che è il flusso che arriva a cliente(0). poi flusso(1) che arriva a cliente(1) e così via...[/COLOR][/FONT]
[FONT=Consolas]TextBox1.Text = [COLOR=#A31515]""[/COLOR] [COLOR=green]'Cancello testo[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]Next[/COLOR] [COLOR=green]'poi[/COLOR][/FONT]
[FONT=Consolas] [COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR][/FONT]
[COLOR=blue][FONT=Consolas]End[/FONT][/COLOR][FONT=Consolas] [COLOR=blue]Class[/COLOR][/FONT]
Potrete notare un “problemino”: ovvero quando scrivete qualcosa dal client nella TextBox del client dove vi vengono raccolti tutti i messaggi vi comparirà 2 volte lo stesso messaggio.
Questo perché una volta viene scritto sul client dallo stesso client. E l’altra dal server che risponde anche a te stesso.
Per risolverlo dovrete fare qualche modifica nel client e togliere la parte dove viene scritto ciò che inviate, oppure nel server e aggiungere di non inviare il messaggio allo stesso client che lo ha inviato.
Altro problema è che quando il Client(0) invia un messaggio a Client(1) viene scritto che è stato inviato da Server. Questo potete risolverlo facendo assegnare dal server un ID (un identificatore univoco) ad ogni client che si connette (potete utilizzare la dimensione stessa dell’array cliente), e il server deve poi inviare a tutti il client anche questo ID agli altri client che così potranno sapere chi ha inviato il messaggio.
EDIT: Risolti i problemi sopra citati. Riporto il messaggio in cui l'ho risolti:
[FONT=&]E wualla fatto non ci è voluto niente
Allora. Va modificato sia il client che il server
Server:
Timer1.Tick diventa:
Client:Codice:For r = 0 To UBound(cliente) 'Per ogni client connesso (contenuto in cliente)... If cliente(r).Available > 0 Then 'Se i dati che ricevi dal cliente che stai controllando (cliente(r)) sono maggiori di 0 e sono disponibili per la lettura allora... Dim temp(cliente(r).Available - 1) As Byte 'Dichiaro un array con dimensioni uguali al numero di dati ricevuti da cliente(r) meno 1 flusso(r).Read(temp, 0, temp.Length) 'Leggo il flusso di dati (flusso(r)) che è il flusso di dati inviato da cliente(r), e metto questi dati dentro all'array temp (byte per byte) per tutta la loro dimensione Dim testo As String = UTF8.GetString(temp) 'Decodifica temp in stringa UTF8 e mettila in testo TextBox2.Text = TextBox2.Text & testo & vbCrLf 'Scrivo nella TextBox2 For s = 0 To UBound(cliente) 'Per ogni client connesso... If Not cliente(s).Equals(cliente(r)) Then flusso(s).Write(temp, 0, temp.Length) 'Scrivo nel flusso di dati (flusso(s)) che è il flusso che arriva a tutti i client, ciò che è contenuto in temp. ovvero invio a flusso(0) che è il flusso che arriva a cliente(0). poi flusso(1) che arriva a cliente(1) e così via... Next 'poi End If 'Fine se Next 'poi
Dopo aver aggiunto una TextBox (TextBox4) che conterrà l'ID scelto dall'utente:
Timer1.Tick diventa:
Button2.Click diventa:Codice:If cliente.Available > 0 Then 'Se i dati che ricevi dal server al quale è connesso cliente sono disponibili e sono maggiori di 0 Dim temp(cliente.Available - 1) As Byte 'Dichiaro un array con dimensioni uguali al numero di dati ricevuti da cliente meno 1 flusso.Read(temp, 0, temp.Length) 'Leggo il flusso di dati Dim testo As String = UTF8.GetString(temp) 'Decodifica temp in stringa UTF8 e mettila in testo TextBox3.Text = TextBox3.Text & testo & vbCrLf 'Scrivo nella TextBox3 End If 'Fine se
Lascio a te scoprire le modifiche che ho fattoCodice:TextBox3.Text = TextBox3.Text & "Io: " & TextBox2.Text & vbCrLf 'Scrivo nella TextBox3 Dim temp() As Byte = UTF8.GetBytes(TextBox4.Text + ": " + TextBox2.Text) 'Decodifica la stringa in TextBox2 in bytes e metti ogni byte nell'array temp flusso.Write(temp, 0, temp.Length) 'Scrivi il flusso di dati TextBox2.Text = "" 'Cancello testo TextBox2.Focus() 'Attivo TextBox2sono poche
Inviare file tra client e server
[/FONT] [FONT=&]Dopo aver stabilito la connessione client/server, oltre che ad inviare messaggi testuali, potete inviare inviare dei file.
Per fare ciò dovrete prendere i bytes che arrivano dal server/client e con questi scrivere un file.
Nell'esempio facciamo un piccolo invio da server a client.
Nel momento in cui volete ricevere il file mettete:[/FONT]
Codice:
[COLOR=blue][FONT=Consolas]Dim[/FONT][/COLOR][FONT=Consolas] bfile(cliente.Available - 1) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR][/FONT]
[FONT=Consolas] flusso.Read(bfile, 0, bfile.Length)[/FONT]
[FONT=Consolas]IO.[COLOR=#2B91AF]File[/COLOR].WriteAllBytes([COLOR=#A31515]"file.ext"[/COLOR], bfile[/FONT][SIZE=3]
[/SIZE]
basta cambiare "file.ext" con il nome e l'estensione che si vuole dare al file.
Per inviare il file invece:[/FONT]
Codice:
[FONT=Consolas] [COLOR=blue]Dim[/COLOR] bfile() [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR] = IO.[COLOR=#2B91AF]File[/COLOR].ReadAllBytes([COLOR=#A31515]"file.ext"[/COLOR])[/FONT]
[FONT=Consolas] fluxconnected(1).Write(bfile, 0, bfile.Length)[/FONT]
[/FONT]
[FONT=&]ReadAllBytes legge invece tutti i bytes di un file.[/FONT][FONT=&]
[/FONT][FONT=&]Non credo siano necessarie ulteriori informazioni.
N.B.: Il codice non è testato. Se qualcuno ha dei problemi e me li segnalasse gliene sarei molto grato.[/FONT]
[FONT=&]Video Guida[/FONT][FONT=&]
[/FONT][FONT=&]Questi video guida vi potranno essere utili per capire meglio come funziona.
In questi video viene solo spiegato come eseguire una connessione tra un client e un server (non una multiconnessione).
Noterete che il codice è simile (non uguale), è infatti da qui che ho imparato (rigrazio Niktor per i suoi semplici ma utilissimi video) e ho poi ricreato il codice da 0 cercando di risolvere i vari problemi.
Infatti il codice di NiktorTheNat (creatore di questi video) non funziona correttamente, e presenta qualche bug.
Vi consiglio quindi di non sostituire questi video alla guida che ho scritto qui sopra ma di seguirli entrambi, in modo da capire bene e vedendo il codice come viene scritto dal video e eliminare gli errori e approfondire meglio i vari passaggi che esegue il codice con la guida scritta.
Ecco i video:
[YOUTUBE]vvxgQidMTfM[/YOUTUBE]
[YOUTUBE]VJmIWxezdtc[/YOUTUBE]
[YOUTUBE]dlMYdkZPzFc[/YOUTUBE]
[YOUTUBE]x5eEg4xiL4c[/YOUTUBE]
[/FONT]
La guida è terminata, spero vi sia stata utile ;-)
Se avete problemi o domande non esitate a chiedere (in questa discussione o con un PM).

[GUIDA] Connettere il client al server con i sockets in vb.net by SpeedJack is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
Based on a work at www.inforge.net
[FONT=&]
[/FONT]
sono poche

).
)
