VB [GUIDA] Connettere il client al server con i sockets in vb.net

Stato
Discussione chiusa ad ulteriori risposte.

SpeedJack

Sviluppatore
Utente Storico
18 Febbraio 2010
5,788
74
3,827
1,419
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 :D 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]
Adesso dichiariamo tre variabili globali, dovremo quindi inserirle subito sotto Public Class Form1. Le variabili sono le seguenti:
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]
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:
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]
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:
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]
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:
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]
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:
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]
AxWindowsMediaPlayer.URL = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + “/song.mp3”
O_O 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]
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:
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]
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:
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]
Adesso dichiariamo due variabili globali:
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]
La variabile del server (servitore) non ci servirà nel client.
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]
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):
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]
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):
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]
Anche questo dovreste essere in grado di capirlo da soli.

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]
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:
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]
Ricreiamo le variabili globali:
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]
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:
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 passiamo subito all’evento Tick del Timer2, e qui vi spiegherò la dimensione degli array.
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]
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:
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]
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 :D 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]
Se avete capito il codice sopra, questo è una sciocchezza :D
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]
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:
E wualla fatto non ci è voluto niente :D
Allora. Va modificato sia il client che il server
Server:
Timer1.Tick diventa:
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
Client:
Dopo aver aggiunto una TextBox (TextBox4) che conterrà l'ID scelto dall'utente:
Timer1.Tick 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
Button2.Click diventa:
Codice:
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 TextBox2
Lascio a te scoprire le modifiche che ho fatto ;) sono poche
[FONT=&amp]

Inviare file tra client e server

[/FONT] [FONT=&amp]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]
[FONT=&amp]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]
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=&amp]
[/FONT]
[FONT=&amp]ReadAllBytes legge invece tutti i bytes di un file.[/FONT][FONT=&amp]
[/FONT][FONT=&amp]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=&amp]Video Guida[/FONT][FONT=&amp]

[/FONT][FONT=&amp]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=&amp]
[/FONT]
 
SpeedJack premetto buon codice, ma sbaglio o il server non è multiconnessione?

No, non è multiconnessione, le cose le noti subito eh ;)... ho voluto spiegarlo così perchè mi era più semplice.
Poi aggiornerò la guida quando avrò un po' di tempo aggiungendo le parti di codice mancanti e da modificare per poter connettere più client.
 
certo certo con calma, hai scritto già un sacco :)

e te pensa solo nella giornata di oggi :) codice creato ora, mentre scrivevo la guida (e inizialmente direttamente su IF, poi ho rinuciato perchè rischiavo di fare errori ed ero insicuro in alcune parti e ho aperto Visual Studio :asd: ).
dalle 16 alle 22 (con 2 ore di pausa che sono stato a tennis) fanno 4 ore... un buon risultato :D

--- Aggiornamento Post ---

Ahahah Preddy ti ho superato in reputazione :P :asd:
 
Vorrei aggiungere che per creare delle applicazioni che devono gestire molti client, secondo me conviene usare le classi della DirectPlay, che permettono di gestire abbastanza facilmente tutti i client connessi ad un server ed i pacchetti in entrata.
 
Vorrei aggiungere che per creare delle applicazioni che devono gestire molti client, secondo me conviene usare le classi della DirectPlay, che permettono di gestire abbastanza facilmente tutti i client connessi ad un server ed i pacchetti in entrata.

nei prossimi giorni aggiornerò la guida aggiungendo anche questo ;-).
 
Speed io ti rispetto assolutamente. Questa guida è stata fatta da NiktorTheNat nel suo video.
Ma tu hai aggiunto le spiegazioni e altre cose più importanti, quindi la reputo tua. :)
A mio parere puoi fare tanto in VB.net ma non lo fai, nel senso che potresti fare grandi progetti ma ti impegni a fare altro meno interessante. (Escluso lo SkypeSitter, grande :\)
P.S: IL tuo code sui numeri random non ha funzionato, quello di Iviblack si xD
 
Ultima modifica:
Allora.
@Nogard --> NiktorTheNat ha fatto un video guida, non una guida (oltretutto la sua non è spiegata molto bene. Si fa comprendere bene ma le sue spiegazioni sono molto vaghe, come dice anche lui stesso). Inoltre puoi notare che il codice non è lo stesso ho dovuto cambiarlo perchè quello di Niktor non funzionava correttamente (se scrivevi ad esempio 2 volte di fila dal server al client il secondo messaggio non arrivava).
Ho aggiunto inoltre un po' di cose (come la CheckBox), e spiegato meglio come connettere due computer.
Sul fatto dei numeri random me lo aspettavo ma ero stanco quella sera :D
Visto che noto lo screen della chat che hai nella firma dico anche che:
1- non sopporto Bill Gates perchè tutti i suoi programmi sono a pagamento e inoltre limita sempre tutti i suoi software (per non parlare poi dei bugs della microsoft :D )
2- non è che voglio usare i programmi e i sistemi operativi della MS "Amorevolmente" :asd: Sono costretto ad utilizzarli perchè il 90% degli utenti utilizza i sistemi/programmi della microsoft, quindi non posso astenermi dall'usarli, altrimenti passerei benissimo a linux ma i programmi per linux sono meno, molti vengono prodotti solo per windows.
Inoltre quest'estate studierò il C e il C++. Ovviamente senza abbandonare il vb che ormai lo uso troppo bene.
Quindi @Preddy & Nogard --> vi sembra davvero un doppio senso? :D

@Teck & Nogard --> La multiconnessione arriverà tra poco in questa stessa guida. Se ho tempo anche proprio oggi. Comunque è semplice potreste anche arrivarci da soli usando un po' di cervello.
 
Ultima modifica:
io ho scritto una dll che gestisce client e server con multiconnessione... dovrei ripulirla dalle funzioni aziendali e condividerla, perchè va molto bene

--- Aggiornamento Post ---

Allora.
1- non sopporto Bill Gates perchè tutti i suoi programmi sono a pagamento e inoltre limita sempre tutti i suoi software (per non parlare poi dei bugs della microsoft :D )
2- non è che voglio usare i programmi e i sistemi operativi della MS "Amorevolmente" :asd: Sono costretto ad utilizzarli perchè il 90% degli utenti utilizza i sistemi/programmi della microsoft, quindi non posso astenermi dall'usarli, altrimenti passerei benissimo a linux ma i programmi per linux sono meno, molti vengono prodotti solo per windows.
Inoltre quest'estate studierò il C e il C++. Ovviamente senza abbandonare il vb che ormai lo uso troppo bene.
Quindi @Preddy & Nogard --> vi sembra davvero un doppio senso? :D
Penso che si ha sempre la possibilità di scegliere, anche se significa distinguersi dalla massa. Piu' che un doppio senso sembra un controsenso :D
Ma se fossi in te non starei li a dar peso a tutto quello che si dice :)

Personalmente ammiro Bill per quello che è riuscito ad ottenere, erano altri tempi, ma assieme ad altri grandi è stato un pioniere su certe cose.
i bug... linux ne è pieno tanto quanto Win...
vedete che ci sono piccoli programmi strapieni di bug, figuriamoci un intero sistema operativo, ci rendiamo conto di cosa significa farlo? E' un bel casino :)
 
Ultima modifica:
io ho scritto una dll che gestisce client e server con multiconnessione... dovrei ripulirla dalle funzioni aziendali e condividerla, perchè va molto bene

--- Aggiornamento Post ---


Penso che si ha sempre la possibilità di scegliere, anche se significa distinguersi dalla massa. Piu' che un doppio senso sembra un controsenso :D
Ma se fossi in te non starei li a dar peso a tutto quello che si dice :)

Personalmente ammiro Bill per quello che è riuscito ad ottenere, erano altri tempi, ma assieme ad altri grandi è stato un pioniere su certe cose.
i bug... linux ne è pieno tanto quanto Win...
vedete che ci sono piccoli programmi strapieni di bug, figuriamoci un intero sistema operativo, ci rendiamo conto di cosa significa farlo? E' un bel casino :)

Si scusa volevo dire controsenso :D
comunque non do peso a quello che dite era solo una precisazione.
Sui bug linux mi sembra funzionare molto meglio. E anche il peso del sistema operativo sulle risorse della macchina mi sembra migliore.
Comunque non capisco perchè dovrebbe ancora sembrarti un controsenso. Mi sembra ovvio che non mi piace utilizzare i sistemi della MS ma sono costretto perchè li usa il 90% del mondo. :D
Comunque condividi la tua dll se funge così bene u.u Ma che intendi con funzioni aziendali? che togli alcune funzioni che lasci solo per una versione "professional" ... non comincerai a fare come Bill Gates :D :asd:
Se fossi in te, rilascerei sia la dll ripulita dalle funzioni aziendali, che è più leggera, sia quella che contiene anche queste funzioni che a volte possono essere utili.

--- Aggiornamento Post ---

Comunque voglio aggiungere che il motivo principale per cui non sopporto Bill Gates è perchè ha avviato un commercio con i suoi software (soprattutto con il suo sistema operativo windows), e quindi tutti i software della MS su basano sulla politica del commercio invece che su quella del miglioramento del software.
Ovvero a Bill Gates non interessa fare dei capolavori di programmi o sistemi operativi, e cercare di migliorarli per renderli più efficienti. A lui interessa soltanto vendere i suoi software per avere un guadagno (motivo per cui cura molto la grafica, che attrae gli utenti).
A differenza, Linus Trovald, autore del kernel Linux, da cui poi è nato il sistema operativo GNU/Linux ottenuto unendo ad esso il sistema GNU (tutto questo discorso per nominare uno che è stato un grande della storia informatica per me :D ), ha creato un software libero (Linux) che quindi non si basa sulla politica del commercio ma punta al miglioramento del software.

Questo discorso tanto per spiegare in modo breve e conciso la mia posizione riguardo la preferenza tra Bill Gates e il suo sistema operativo Windows e Linus Trovald e il suo sistema operativo Linux.
Ovviamente ognuno la pensa poi come vuole u.u
 
Bhe la tua enorme paginata dice il contrario :sisi:

perchè ho detto di essermi scaldato? O.o

Questo discorso tanto per spiegare in modo breve e conciso la mia posizione riguardo la preferenza tra Bill Gates e il suo sistema operativo Windows e Linus Trovald e il suo sistema operativo Linux.
Ovviamente ognuno la pensa poi come vuole u.u

Mi sembra di aver detto che il discorso era solo per spiegare la mia posizione.
comunque ho scritto la parte della multiconnessione sul notepad :P ora l'aggiungo alla guida.
 
Ultima modifica:
Comunque voglio aggiungere che il motivo principale per cui non sopporto Bill Gates è perchè ha avviato un commercio con i suoi software (soprattutto con il suo sistema operativo windows), e quindi tutti i software della MS su basano sulla politica del commercio invece che su quella del miglioramento del software.
Ovvero a Bill Gates non interessa fare dei capolavori di programmi o sistemi operativi, e cercare di migliorarli per renderli più efficienti. A lui interessa soltanto vendere i suoi software per avere un guadagno (motivo per cui cura molto la grafica, che attrae gli utenti).
A differenza, Linus Trovald, autore del kernel Linux, da cui poi è nato il sistema operativo GNU/Linux ottenuto unendo ad esso il sistema GNU (tutto questo discorso per nominare uno che è stato un grande della storia informatica per me :D ), ha creato un software libero (Linux) che quindi non si basa sulla politica del commercio ma punta al miglioramento del software.

Questo discorso tanto per spiegare in modo breve e conciso la mia posizione riguardo la preferenza tra Bill Gates e il suo sistema operativo Windows e Linus Trovald e il suo sistema operativo Linux.
Ovviamente ognuno la pensa poi come vuole u.u
si chiariti che dire cose tipo controsenso sono solo modi di dire e battute eh :)
sul fattore microsoft/linux forse è meglio precisare un po di cosette:
premesso che oggi come oggi non esiste un sistema migliore dell'altro, cioè che Windows è migliore su certi aspetti rispetto a Linux e viceversa....
e premesso che Bill Gates non lavora piu' in Ms da un po', perchè si è dimesso da Microsoft nel 2008...
Microsoft "nasce" circa nel 1975, e 36 anni fa l'informatica come la conosciamo ora era fantascienza... anche solo 10 anni fa era fantascienza.
Nel 1985, esce Windows 1.0 che era piu' che altro una interfaccia grafica del dos... fino alla versione 3.0 nel 1992 che inizio' ad avere una differenza sostanziale.
Il vero colpo di successo arrivo' con Windows 95, un sistema ibrido nel quale gira 16 e 32 Bit... e a seguire lo sappiamo le varie versioni fino ad oggi.
Ora dimmi, se chiunque 30 anni fa avesse creato windows, avesse provato a venderlo o l'avesse regalato a tutti.
Al tempo, quando quel sistema era unico su tutti, sono convinto che nessuno ma nessuno avrebbe perso l'occasione di vendere un prodotto del genere.
Altra cosa: la competizione genera qualità. In un mondo privo di competizione, nessuno avrebbe vero interesse ad emergere. Se non ci fosse il mercato del software non ci sarebbero i grandi software che conosciamo, tantomeno giochi cosi' belli.
Lo dimostra il fatto pratico che, nonostante siano passati una vagonata di anni, linux continua ad essere notevolmente sprovvisto di software qualitativamente paragonabili a quelli su windows. Possiamo fare un elenco interminabile. E attenzione non sto confrontando win e linux, ma le applicazioni che vi girano.
Ecco che linux si vede "costretto" a fare Wine. Prodotto bellissimo che fa girare applicazioni non sue. ecc...

Microsoft (non Bill che non ci lavora piu') ha interesse a migliorare il suo OS, e Windows 7 ne è la prova.
Mettere grafica carina è un di piu', e non è vero che linux è graficamente inferiore. Installiamo KDE e le varie figatine grafiche e otteniamo un aspetto similissimo a win.
Software libero non è sinonimo di software migliore.
Linux, ha copiato parecchio da windows, prova ad informarti sul Cache Manager sul FastIO e vedi da chi l'hanno copiato per inserirlo in linux. Ma non vorrei mai al mondo cadere in un linux vs win dato che come ho detto prima non esiste uno migliore dell'altro.
Se non ci fosse il mercato del software, apparte che io ora sarei disoccupato LOL, non ci sarebbero nemmeno i bei software che oggi usiamo.
E non si puo' incolpare un inventore di aver venduto la propria creazione.
Utopia esiste solo su star trek, dove tutti regalano a tutti. tutti possono avere la ferrari perchè c'è chi le fa per regalarle e chi regala il pane e chi regala altro...
In questi due anni windows è migliorato sforgiando seven, linux è peggiorato appesantendo il kernel (parole di Trovald).

In sintesi: la competizione migliora il prodotto.

--- Aggiornamento Post ---


Tornando intopic, sia io che MetalMaster riteniamo questa guida di SpeedJack meritevolissima e l'abbiamo messa in rilievo :)
e do anche un personale +1 :)

Pred
 
Ultima modifica:
Vorrei farti notare che in una parte del codice per la multiconnessione hai posto le dimensioni di alcuni array a -1. Questo è sbagliato, perchè il numero tra parentesi indica il numero di celle, quindi non si possono avere -1 celle per immagazzinare valori...(spero di essermi spiegato correttamente :P) se si vuole creare un array vuoto(inteso come un array che non può contenere elementi) bisogna impostarne a 0 la dimensione. Probabilmente ti sarai confuso con l'indice di quando si vuole prendere un valore dall'array.

Comunque ti consiglio di usare la classe ArrayList al posto dei normali array, poiché si gestisce facilmente e si ridimensiona da sola a seconda degli elementi contenuti.

Saluti.
 
Vorrei farti notare che in una parte del codice per la multiconnessione hai posto le dimensioni di alcuni array a -1. Questo è sbagliato, perchè il numero tra parentesi indica il numero di celle, quindi non si possono avere -1 celle per immagazzinare valori...(spero di essermi spiegato correttamente :P) se si vuole creare un array vuoto(inteso come un array che non può contenere elementi) bisogna impostarne a 0 la dimensione. Probabilmente ti sarai confuso con l'indice di quando si vuole prendere un valore dall'array.

Comunque ti consiglio di usare la classe ArrayList al posto dei normali array, poiché si gestisce facilmente e si ridimensiona da sola a seconda degli elementi contenuti.

Saluti.

Ma che problemi ti fai? funziona anche così ora l'ho testato :D almeno a me xD
-1 celle (o spazi come li chiamo io ma è uguale) non ha significato. però Visual Basic lo accetta li stesso perchè lo prende come se non esistessero celle (come se l'array non esistesse). In sostanza l'ho solo dichiarato senza applicargli nessuna cella. Quindi più avanti quando scrivo Array.Resize(cliente, cliente.length + 1) aumento la sua dimensione a 0.
Ti faccio notare che a dimensione 0 l'array può contenere elementi (appunto alla cella 0) quindi per evitare di dover saltare una cella e complicarmi di più in altre parti del codice ho preferito dargli come dimensione -1... così quando andavo a ridimensionarlo la sua dimesione sarebbe aumentata a 0 e io avrei potuto utilizzare quella cella (cliente(0)).
Potevo si utilizzare 0 come dimensione iniziale ma avrei poi dovuto in tutti i For r = 0 To Ubound(cliente) un 1 al posto dello 0, e la cella 0 sarebbe andata sprecata.
Se io facessi come dici tu quando vado a prendere il valore dall'array mi restituisce un'eccezione (NullReferenceException) perchè nella cella 0 non ho inserito niente.
Sull'array list si era meglio e magari nei prossimi giorni lo sistemo xD.

@Predator
Prima di tutto, cosa più importante, vi ringrazio. Sia te che Metal per il rilievo :D e te anche per il +1. Grazie.
Poi sul fatto della Microsoft e della Linux :asd: ...
Mettiamo fine a questa discussione, mi si bloccano le dita sulla tastiera a forza di scrivere :asd:
Per rispondere al tuo discorso, in alcune parti dovrei entrare nella politica, e non voglio (sono estremista di sinistra), soprattutto in un forum che dalla politica non è proprio staccato ma quasi. Solo un breve discorso sulla concorrenza:
Dici che la concorrenza per le vendite per avere un guadagno porta a dei miglioramenti del software.
è giusto!
ma...ti faccio notare alcuni piccoli dettagli (ormai ho le dita incollate alla tastierà *,_,*):
La Microsoft (o Bill Gates che può comunque esserne considerato il rappresentante avendola fondata, anche se da qualche anno si è ritirato) ha una scarsissima concorrenza. Linux viene poco utilizzato.
La concorrenza può esistere anche senza un guadagno. E il problema di una concorrenza di questo tipo è che (certo funziona) ma si tenta a migliorare il programma perchè possa essere apprezzato nel miglior modo possibile dagli utenti, ma non si punta direttamente al miglioramento. Al miglioramento ci punti solo per passione nella programmazione.
Ovvero ti faccio un esempio fuori dalla Microsoft:
Se una pianta di pomodori tiene al massimo 5 pomodori ma una pianta OGM ne tiene 8 (non so quante ne tengono in media veramente :D) al coltivatore quale li conviene??? Ovviamente la seconda.
Certo c'è anche un miglioramento: più produzione di pomodori ma... gli OGM non sono ancora ben testati e possono portare molti problemi ai consumatori.
Ma al coltivatore che gliene frega??? :D
Se invece le cose vengono fatte diversamente e prima si testano gli OGM forse si arriverà ad avere piante con 8 pomodori 70 anni più tardi, ma sicuramente non fanno danni.
Ecco il motivo per cui non mi piace la concorrenza per guadagno. Oltre al fatto che inserendo dei prezzi chi ha problemi economici non può permettersi quei prodotti.
Sul fatto della creazione è vero che è fastidioso darlo in giro senza alcun guadagno, ma a me ad esempio darebbe più fastidio impedire che molti persone, per problemi economici, non possono utilizzare i software. è questione di punti di vista.
Sul guadagno comunque io posso essere d'accordo su una cosa:
Vendere il software alle aziende (che possono sempre permetterselo) ma non hai privati.
Un esempio ne è TeamViewer (software per l'assistenza remota) che ti permette di utilizzarlo gratuitamente per uso privato ma non per uso commerciale.
Chiunque nella situazione di Bill Gates avrebbe aperto un commercio (c***o se ti fa diventare il più ricco del mondo lo fai di sicuro) però in una società come quella di ora....in altre magari.... (non entro nella politica)

Adesso basta con questo discorso che mi ha fatto stare 1 ora e mezzo di più davanti al pc ^^ xD. Se vuoi fai qualche conclusione ma poi basta non possiamo parlare della MS a vita, ci siamo espressi sulle nostre idee e abbiamo riflettutto.
Vi ringrazio un altra volta per il rilievo e per il +1 ^^
Ora vado a chiudere gli occhi che tra computer e cinema si sono arrostiti @.@ notte.
 
Ma che problemi ti fai? funziona anche così ora l'ho testato :D almeno a me xD
-1 celle (o spazi come li chiamo io ma è uguale) non ha significato. però Visual Basic lo accetta li stesso perchè lo prende come se non esistessero celle (come se l'array non esistesse). In sostanza l'ho solo dichiarato senza applicargli nessuna cella. Quindi più avanti quando scrivo Array.Resize(cliente, cliente.length + 1) aumento la sua dimensione a 0.
Ti faccio notare che a dimensione 0 l'array può contenere elementi (appunto alla cella 0) quindi per evitare di dover saltare una cella e complicarmi di più in altre parti del codice ho preferito dargli come dimensione -1... così quando andavo a ridimensionarlo la sua dimesione sarebbe aumentata a 0 e io avrei potuto utilizzare quella cella (cliente(0)).
.
Infatti Vb.Net non vuole la lunghezza dell'array come parametro, ma "l'indice dell'ultimo elemento". Quindi dire (0) significa dire che c'è un elemento con indice 0

--- Aggiornamento Post ---

per fare un array vuoto sarebbe più sensato non mettere niente come parametro:
dim x() as byte
 
coff coff guarda che c'è parecchio di sbagliato, sono luoghi comuni senza supporto di documentazione, poi che sfiga, hai preso proprio TeamViewer che è l'esempio sbagliato XD
TeamViewer è gratuito per uso personale... ma hehe a tempo limitato (sorpresina!). Io l'ho usato per un paio di giorni, poi iniziano a spuntare fuori messaggi che dicono che è usato troppo e si chiude. Anche a distanza di giorni, perchè memorizza l'utilizzo in locale.
Pertanto anche TeamViewer alla fine dei conti è un 100% trial e un finto free.
Sul vendo/regalo, non esiste il problema. Chi vende non obbliga nessuno ad acquistare, chi regala non obbliga nessuno ad utilizzare. Se chi vende è superiore a chi regala ci saranno dei macro motivi :-)
 
Mo me la pappo tutta!!
Sei stato bravo, e ti meriti il rilievo!


Funge alla stragrande, bravissimo :D
 
Stato
Discussione chiusa ad ulteriori risposte.
Indietro
Top Bottom