[Perchè studiare i sockets?] Lo studio dei sockets, a mio parer, è uno degli argomenti più interessanti che ruotano nel mircscripting. Per poterli affrontare\studiare bisogna aver acquisito una solida padronanza su quelle che son le basi del linguaggio. (Vedi Alias-Identificatori-Manipolazione variabili). Inizialmente la loro gestione potrebbe sembrar complicata, ma poi, utilizzandoli frequentemente, vi accorgerete che "Il grosso" sta nel sistemarvi i dati (ingresso\uscita) in base a ciò che si vuole.
[Sì ma, che sono i sockets?] La socket puo esser vista come lo "strumento" che permette l'interfacciamento e la comunicazione tra macchine in rete. Più in dettaglio, permette di aprire\ricevere connessioni dal\verso il nostro client mIRC.
[Abbiam parlato di connessioni..Che tipi di connessioni si possono gestire?] Dipende dal programmatore. i protocolli di comunicazione più utilizzati in ambiente mircscript sono:
- HTTP (Connessione verso siti web: porta 80) - FTP (Per il trasferimento di File in rete: porta 21) - IRC (Connessioni su reti IRC: porta 666x) - SMTP (Connessione al server per invio della posta: porta 25) - POP3 (Connessione al server per ricezione della posta: porta 110) - SHTTP (Estensione dell'HTTP per connessioni sicure: porta 80) only for nerd ;Þ
[In che maniera posso utilizzare i sockets negli script?] Il linguaggio offre ottimi strumenti sottoforma di Comandi, identificatori ed Eventi;
Comandi:
/sockopen [nome] [indirizzo] [porta] Esempio:/sockopen prova www.irc-zone.org 80 Il comando apre una connessione di nome "prova" verso l'indirizzo (ovviamente web: porta 80) www-irc-zone.org.
/sockclose [nome] Esempio:/sockclose prova Chiude la connessione "prova" (precedentemente aperta)
/socklist [nome] Esempio:/socklist prova Ritorna alcune informazioni sulla connessione prova. (Se non specificato alcun nome, stampa tutte le connessioni attive)
/socklisten [nome] [porta] Esempio:/socklisten prova 65000 Apre una connessione di nome prova sulla porta 65000 e si tiene in ascolto nel caso in cui "qualcosa" esterna voglia connettersi.
/sockaccept [nome] Esempio:/sockaccept prova Accetta la connessione prova (precedentemente aperta e tenuta in ascolto su una porta) e le attribuisce un nome.
/sockwrite [-tnb] [nome] [numbytes] [testo|%variabile|&binvar] Esempio:/sockwrite -tn prova GET /index.html HTTP/1.1 Permette di INVIARE informazioni ad una connessione in precedenza aperta. Nell'esempio quì sopra, si sta chiedendo di ricevere tramite metodo GET (vedi rfc protocollo HTTP) la pagina web "index.html" di una presunta connessione che abbiamo aperto (vedi /sockopen). I parametri di questo comando sono: -t Comanda al mIRC che se dovesse incontrar qualcosa che inizi per "&", che lo prenda come normale testo e non come variabile binaria (Vedi &Binvar) -n Aggiunge un carattere CRLF alla fine di ogni linea che si sta inviando. -b Indica il numero di byte che si sta inviando. (Inizialmente potete anche evitare di utilizzarli in situazioni non troppo complicate)
/sockread [-fn] [numbytes] [%variabile|&Binvar] Esempio:/sockread %Testo_pagina_web Memorizza nella variabile %Testo_pagina_web tutto ciò che riceve dalla connessione. Ogni linea seguita da un carattere CRLF
/sockrename [nome_attuale] [nome_nuovo] Esempio:/sockrename prova prova_2 Rinomina una connessione esistente.
/sockmark [nome] [testo] Esempio:/sockmark prova Il_valore Memorizza Il_valore nell'attributo ".mark" della connessione prova [Potrà essere prelevato in seguito con l'utilizzo dell'identificatore $sock(prova).mark]
Identificatori:
$sock(nome,n) Esempio:/sockopen prova www.irc-zone.org 80 //echo -a $sock(prova) <- Riceveremo "prova". Ciò significa che la connessione è aperta. Ritorna il nome del socket se questi è esistente (aperto) Seguono poi una serie di parametri che si posson specificare nel comando. Eccovi quelli maggiormente utilizzati: $sock(nome).ip - restituisce l'ip della connessione "nome" $sock(nome).port - restituisce la porta di comunicazione $sock(nome).status - restituisce lo stato della connessione (se attiva o meno) $sock(nome).mark - Se precedentemente memorizzato, (/sockmark nome Valore) ne restituisce il "Valore" $sock(nome).name - Il nome della connessione $sock(nome).sent - restituisce il numero di bytes inviati dal momento in cui è stata avviata la connessione $sock(nome).rcvd - bytes ricevuti $sock(nome).to - restituisce il tempo trascorso dal momento in cui si è aperta la connessione ad ora (espresso in secondi) Mi permetto di non specificare gli altri parametri per un discorso di poca utilità.
$sockname Esempio:/sockopen prova www.irc-zone.org 80 //echo -a $sockname <- Riceveremo "prova" $sockerr Controlla se ci son errori durante la connessione e si setta diverso da 0
$sockbr Esempio:/sockread %prova //echo -a $sockbr Restituisce il numero di bytes letti dopo il comando (/sockread) sino alla chiusura della connessione
Gli eventi:
Evento SOCKOPEN on *:sockopen:nome_socket: { ..comandi.. } Esempio: /sockopen prova www.irc-zone.org 80 on *:sockopen:prova: { echo -a Connessione su IRC-ZONE avvenuta! } La prima riga vi dovrebbe esser già abbastanza chiara. (Apriamo un socket di nome prova su www.irc-zone.org) Successivamente gli piazziamo l'evento SOCKOPEN che si traduce nella seguente maniera: Quando un qualsiasi utente apre un socket di nome "prova", echa che la Connessione è avvenuta.
Evento SOCKCLOSE on *:sockclose:nome_socket: { ..comandi.. } Esempio: /sockopen prova www.irc-zone.org 80 on *:sockclose:prova: { echo -a Connessione su IRC-ZONE terminata! } Stesso discorso di prima, operazione inversa :)
Evento SOCKLISTEN on *:socklisten:nome_socket: { ..comandi.. } Esempio: /socklisten prova 65000 on *:socklisten:prova: { echo -a Rilevato tentativo di connessione | /sockaccept prova_2 | echo -a Connessione accettata! } L'evento SOCKLISTEN scatta nel momento in cui qualcuno tenta di connettersi alla porta 65000 messa precedentemente in ascolto. Successivamente, rilevato il tentativo di connessione, l'accetta.
Evento SOCKWRITE on *:sockwrite:nome_socket: { ..comandi.. } L'evento scatta qualora vengano inviate tutte le informazioni precedentemente messe in coda. (/sockwrite)
Evento SOCKREAD on *:sockread:nome_socket: { ..comandi.. } L'evento scatta qualora si stia tentando di leggere le informazioni sulla connessione nome_socket (/sockread)
Dopo aver fatto una buona paronamica sui comandi\identificatori\eventi che girano attorno ai sockets, andiamo ad attuarli in un piccolo ma simpatico script d'esempio: Creare una semplice chat privata tra due utenti che comunicano su una porta non standard :) Lo script si suddivide in due parti distinte: script lato SERVER <- Colui che dovrà mettersi in ascolto su una porta ed attendere la connessione dall'altra parte script lato CLIENT <- Colui che si connetterà alla macchina che mette a disposizione la connessione. Iniziamo con lo script che dovrà essere caricato da chi vuole iniziare la comunicazione (Server):
# Script Lato Server @Chat privata by Sp .1 alias server_join { socklisten server_privato 65000 | echo -a Server di Chat privata avviato su porta 65000..in attesa di connessione. } .2 on *:socklisten:server_privato: { .3 sockaccept chat_privata .4 echo -a $sock(chat_privata).ip si è connesso alla chat. .5 sockwrite -tn chat_privata Benvenuto :) Connessione avvenuta con successo! } .6 on *:sockread:chat_privata: { sockread %testo | echo -a Utente_privato dice -> %testo } .7 alias scrivi { echo -a Io -> $1- | sockwrite -tn chat_privata $1- } .8 alias chiudi { $iif($sock(chat_privata),sockwrite -tn chat_privata l'Admin si è disconnesso. Alla prossima!) | sockclose chat_privata | echo -a Connessione Terminata! | sockclose server_privato }
Spiegazione:
.1 Imposto il comando dell'alias (/server_join) che permette di avviare una connessione di nome server_privato con il proprio IP mettendola in ascolto sulla porta 65000 .2 Creo l'evento SOCKLISTEN per la connessione server_privato in modo tale da farlo scattare nel momento in cui qualcuno si connette .3 In caso di connessione esterna, si accetta e la si rappresenta con il nome chat_privata .4 Ricevo l'indirizzo IP della persona che si è connessa al server [$sock(nome_connessione).ip] .5 A questo punto, avviso l'utente che la connessione è avvenuta con successo tramite l'utilizzo del SOCKWRITE .6 Apro un evento SOCKREAD in modo tale possa ricevere tutto ciò che l'altro lato invia tramite SOCKWRITE (Il testo) .7 Imposto il comando dell'alias (/scrivi) per poter comunicare con l'altro lato .8 Imposto il comando dell'alias (/chiudi) nel caso in cui si voglia disconnettere e chiudere il server. Non si fa altro che avvisare l'utente della disconnessione e chiudere le due connessioni: - server_privato <- Connessione primaria del server - chat_privata <- Connessione privata con l'utente Ho tralasciato la spiegazione di alcune sintassi che credo siano scontate (L'utilizzo del simbolo pipe "|" per inserire più comandi sulla stessa riga, il simbolo asterisco "*" (wildcards) su ogni evento che sta a significare "qualsiasi", la creazione di Alias su remote, ect)
Passiamo adesso allo script lato CLIENT:
.1 alias client_join { sockopen chat_privata $$?="Chat privata. Inserisci L'IP del server" 65000 | echo -a Apertura Connessione Server Chat! } .2 on *:sockopen:chat_privata: { sockwrite -tn $sockname Connessione Stabilita! | echo -a Puoi iniziare a comunicare con l'utente (/scrivi) } .3 on *:sockread:chat_privata: { sockread %testo | echo -a l'Admin dice -> %testo } .4 alias scrivi { echo -a Io -> $1- | sockwrite -tn chat_privata $1- } .5 alias chiudi { sockwrite -tn chat_privata Utente_privato si è disconnesso, alla prossima! | sockclose chat_privata | echo -a Connessione .6 Terminata. | halt }
Spiegazione:
.1 Imposto il comando dell'alias (/client_join). Lo script chiederà L'IP del server dove connettersi che ovviamente dovrà essere comunicato dall'altra persona bindato su porta 65000; .2 Apro un evento SOCKOPEN in modo tale che scatterà nel momento in cui si prova la connessione e subito dopo si avvisa l'altro lato che si è pronti per chattare :) .3 Stesso discorso del lato SERVER .4 Idem .5 idem [Ovviamente il lato CLIENT chiude soltanto la connessione privata (chat_privata)]
Riassumendo, i comandi per la chat privata:
LATO SERVER: /server_join <- Avvia il server per la chat /scrivi <- Permette di inviare del testo all'altro utente /chiudi <- Disconnette dalla chat e chiude il server
LATO CLIENT: /client_join <- Si connette al server chat /scrivi <- IDEM al lato server /chiudi <- Disconnette dalla chat Spero di esser stato più chiaro possibile. Vi prego vivamente, per una mia questione personale, di farmi sapere il proprio giudizio riguardo al seguente tutorial. Alla prossima :)
Se vuoi scaricare lo script clicca sui link qui sotto: