Adesso il server deve creare la socket e mettersi in ascolto, quindi
In questa parte di codice creiamo una socket TCP/IP, la impostiamo in modalità NON-BLOCKING, ovvero il programma continuerà a lavorare e i comandi come socket_read e socket_write restituiranno SEMPRE false perché non attenderanno l'esecuzione del comando che potrebbe riuscire come non potrebbe riuscire, però questo ci permette di eseguire altre operazioni nel frattempo senza bloccare il programma e rallentare pesantemente il sistema operativo.codice:// Creiamo la socket $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // Controlliamo se ha dato errore o meno if ($socket === FALSE) { // Se si il programma muore restituendo l'errore die("Errore durante la creazione della socket!\n" . socket_strerror(socket_last_error()) . "[" . socket_last_error() . "]\n"); } // Impostiamo la socket come non blocking socket_set_nonblock($socket); // Impostiamo la socket come riusabile socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1); // Bindiamo la socket $ris = socket_bind($socket, $_CONFIG['host'], $_CONFIG['port']); if ($ris === FALSE) { die("Impossibile impostare la socket!\n" . socket_strerror(socket_last_error()) . "[" . socket_last_error() . "]\n"); } // Mettiamo in ascolto la socket $ris = socket_listen($socket); if ($ris === FALSE) { die("Impossibile mettersi in ascolto sulla porta {$_CONFIG['host']}:{$_CONFIG['port']}!\n" . socket_strerror(socket_last_error()) . "[" . socket_last_error() . "]\n"); } // Leggiamo la lista degli utenti registrati e la inseriamo nell'array $tmparr = file("userlist.usr"); while (list(, $value) = each($tmparr)) { list($nick, $pass) = explode('|', $value); $_REGLIST[$nick] = array( 'nick' => $nick, 'pass' => $pass ); }
Dopo di ciò impostiamo la socket in modalità REUSABILE, dopo di che diciamo che IP e PORTA deve usare la socket! Fatto ciò possiamo dire di mettersi in ascolto. In questo codice abbiamo inserito un minimo di gestione degli errori.
Creiamo alcune funzioni che gestiranno l'invio dei dati a tutti gli utenti e l'avvertenza di quando uno si disconnette o entra
La prima funzione si occupa di scrivere nella socket le stringe che gli inviamo! E' importante quel while perché attende che sia possibile scrivere nella socket, se non lo facessimo potremmo avere errori a causa di grandi quantità di dati inviati alla socket remota.codice:// Funzione per scrivere nei socket function sock_write(&$socket, $data, $return = TRUE) { // Inizializza la variabile $num = 0; // Attende che il numero di socket in cui si può scrivere è maggiore di zero while ($num > 0) { // Crea un'array dove inserisce la socket in cui scrivere $array = array($socket); // Avvia il select sulla socket interessata $num = socket_select($r = NULL, $array, $e = NULL, 0, 10); } // Controlla se alla fine della stringa ci sta il \n if ($data{strlen($data)-1} != "\n" && $return) $data .= "\n"; // Invia i dati socket_write($socket, $data); } // Funzione per gestire i nuovi utenti function new_user($nick) { global $_CLIENTS_INFO, $_CLIENTS_SOCK; // Cicla tutte le socket foreach($_CLIENTS_SOCK as $socket) { // Controlla se la socket indicata può chattare if ($_CLIENTS_INFO[(int) $socket]['state'] != STATE_CANCHAT) continue; // Invia il messagio sock_write($socket, "User <{$nick}> connected!"); } } // Gestione per la disconnessione di un utente function quit_user(&$sock, $advise = TRUE) { global $_CLIENTS_NICK, $_CLIENTS_INFO, $_CLIENTS_SOCK; // Recupera il nick $nick = $_CLIENTS_NICK[(int) $sock]; // Controlla se deve avvisare if ($advise) { // Cicla l'array delle socket foreach($_CLIENTS_SOCK as $socket) { // Controlla che l'interessato possa chattare if ($_CLIENTS_INFO[(int) $socket]['state'] != STATE_CANCHAT) continue; // Se si invio il messagio sock_write($socket, "User <{$nick}> exit!"); } } // Chiude la socket socket_close($sock); // Scarica i vari riferimenti unset($_CLIENTS_INFO[(int) $sock]); unset($_CLIENTS_SOCK[(int) $sock]); unset($_CLIENTS_NICK[(int) $sock]); // Elimina la socket unset($sock); } // Gestione della chat function chat_user($from_sock, $msg) { global $_CLIENTS_INFO, $_CLIENTS_NICK, $_CLIENTS_SOCK; // Estrae il nick $from_nick = $_CLIENTS_NICK[(int) $from_sock]; // Si cicla l'array delle socket foreach($_CLIENTS_SOCK as $socket) { // Controlla che la socket selezionata non sia quella di provenienza e che possa chattare if ($from_sock == $socket || $_CLIENTS_INFO[(int) $socket]['state'] != STATE_CANCHAT) continue; // Scrive il messagio sock_write($socket, "<{$from_nick}> {$msg}"); } } // Funzione per recuperare il nick dalla socket function getsockfromnick($nick) { global $_CLIENTS_NICK, $_CLIENTS_SOCK; while(list($key, $value) = each($_CLIENTS_NICK)) { if ($value == $nick) return $_CLIENTS_SOCK[$key]; } return FALSE; } // Funzione per controllare se un utente è registrato o meno function user_is_regged($nick) { global $_REGLIST; if (isset($_REGLIST[$nick])) return TRUE; return FALSE; } // Funzione per controllare se user e pass corrispondono function check_user($nick, $pass) { global $_REGLIST; if ($_REGLIST[$nick]['nick'] == $nick && $_REGLIST[$nick]['pass'] == $pass) return TRUE; return FALSE; } // Gestisce i messagi privati function privatechat_user($from_sock, $to_nick, $msg) { global $_CLIENTS_INFO, $_CLIENTS_NICK, $_CLIENTS_SOCK; // Estrae la socket dal nick $socket = getsockfromnick($to_nick); // Estrae il nick dalla socket $from_nick = $_CLIENTS_NICK[(int) $from_sock]; // Controlla che il nick esista if ($socket === FALSE) { // Se non esiste avverte che l'utente non c'è sock_write($from_sock, "Unable to find <{$to_nick}>"); } else { // Esiste, quindi controlla che chi deve ricever il messaggio può chattare if ($_CLIENTS_INFO[(int) $socket]['state'] != STATE_CANCHAT) { sock_write($from_sock, "Unable to find <{$to_nick}>"); } // Invia il messagio sock_write($socket, "PRIVATE: <{$from_nick}> {$msg}"); } }
La seconda funzione si occupa di avvertire tutti gli utenti connesi che è entrato un nuovo utente, mentre la terza che un utente è uscito. Infine la quarta funzione si occupa di inviare i messaggi della chat ai vari utenti
La quinta funzione controlla se un utente è registrato o meno, la sesta controlla la pass di accesso ed infine la settima gestisce i messaggi privati
continua...

Rispondi quotando