Pagina 1 di 3 1 2 3 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 23
  1. #1

    [CLASSE SOCKET] Struttura per gestire tutto in maniera sincrona

    Hola

    vi posto un po di codice che ho scritto oggi pome

    codice:
    <?php
    	
    	/*
    	 * +----------+
    	 * |   TODO   |
    	 * +----------+
    	 * - Completare l'elenco delle funzioni e scriverle
    	 * - Implementare il sistema per gestire le callbacks
    	 * 
    	 * +----------+
    	 * |   NOTE   |
    	 * +----------+
    	 * - Tutto deve essere gestito dalla routine doevents (connessione, lettura dati, scrittura dati e altro ancora)
    	 * 
    	 * +--------------+
    	 * |   FUNZIONI   |
    	 * +--------------+
    	 * - [OK] clsSocket
    	 * - [OK] connect
    	 * - [OK] close
    	 * - [OK] bind
    	 * - [OK] __set_error
    	 * - [OK] __log
    	 * - [!!] doEvents
    	 * - [NO] write
    	 * - [NO] read
    	 * - [NO] listen
    	 * - [NO] set_callback
    	 * - [NO] get_strerror
    	 * - [NO] __manage_callbacks
     	 */ 
    	
    	// Stati classe pubblici
    	define('S_SOCKET_CLOSED'		, "\x00");
    	define('S_SOCKET_CONNECTING'	, "\x01");
    	define('S_SOCKET_CONNECTED'		, "\x02");
    	define('S_SOCKET_WRITING'		, "\x03");
    	define('S_SOCKET_LISTING'		, "\x04");
    	
    	class clsSocket {
    		
    		/* 
    		 * Public Vars
    		 */ 
    		var $local_host = "";						// Indirizzo Locale
    		var $local_port = 0;						// Porta locale
    		var $remote_host = "";						// Indirizzo Remoto
    		var $remote_port = 0;						// Porta remota
    		var $state = S_SOCKET_CLOSED;				// Stato della connessione
    		
    		/* 
    		 * Private Vars
    		 */ 
    		var $__conn_starttime = 0;					// Avvio tentativo di connessione
    		var $__conn_timeout = 0;					// Timeout di connessione
    		var $__oSocket = 0;							// Oggetto della socket
    		var $__error_code = 0;						// Codice d'errore interno
    		
    		// Costruttore della classe
    		function clsSocket() {
    			
    			// Controlla se l'estensione specifica per le socket è stata caricata
    			if (!extension_loaded('sockets')) {
    				
    				// Carica i settaggi dal file ini
    				$php_ini = ini_get_all();
    				
    				// rileva se il safe mode è attivo o il DL è stato disabilitato da php.ini
    				if (
    						(
    							isset($php_ini['enable_dl']['local_value']) == FALSE ||
    							$php_ini['enable_dl']['local_value'] == ''
    						) || (
    							isset($php_ini['safe_mode']['local_value']) == TRUE &&
    							$php_ini['safe_mode']['local_value'] == 1
    						)
    					) {
    				    $this->__log('FATAL', 'SAFE MODE attivo o DL disabilitato! Impossibile caricare a run-time il modulo Sockets!', TRUE, TRUE);
    				}
    				
    				// Crea il prefisso
    				$prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
    				
    				// Prova a caricare l'estensione
    				if (!@dl($prefix . 'sockets.' . PHP_SHLIB_SUFFIX)) {
    				    $this->__log('FATAL', 'Caricamento del modulo Sockets fallito!', TRUE, TRUE);
    				} else {
    					$this->__log('NOTICE', 'Modulo Sockets caricato correttamente');
    				}
    				
    			}
    			
    			// Crea la socket
    			$this->__oSocket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    			
    			// Controlla se la creazione è correttamente riuscita
    			if (!is_resource($this->__oSocket)) {
    			    $this->__log('FATAL', 'Creazione della socket fallita! - Errore: ' . socket_strerror(socket_last_error()), TRUE, TRUE);
    			}
    			
    			// Imposta la socket in modalità non blocking
    			$res = @socket_set_nonblock($this->__oSocket);
    			
    			// Controlla se l'operazione è riuscita
    			if (!$res) {
    			    $this->__log('FATAL', 'Impossibile impostare la socket in modalità non blocking! - Errore: ' . socket_strerror(socket_last_error($this->__oSocket)), TRUE, TRUE);
    			}
    			
    			// Imposta la reusabilità della socket
    			$res = @socket_set_option($this->__oSocket, SOL_SOCKET, SO_REUSEADDR, 1);
    			
    			// Controlla se l'operazione è riuscita
    			if (!$res) {
    			    $this->__log('FATAL', 'Impossibile impostare la socket in modalità riusabile! - Errore: ' . socket_strerror(socket_last_error($this->__oSocket)), TRUE, TRUE);
    			}
    			
    		}
    		
    		// Questa funzione si occupa di gestire gli eventi
    		function doEvents() {
    			
    			// Controlla lo stato della socket
    			switch($this->state) {
    				
    				case S_SOCKET_CLOSED:		// Non fa nulla
    					break;
    					
    				case S_SOCKET_CONNECTING:	// Gestisce la connessessione ad un host
    					
    					// Dichiara alcune vars
    					$tmpINT_ConnStatus = 0;
    					
    					// Controlla se la connessione è riuscita correttamente
    					$tmpARRAY_write = array($this->__oSocket);
    					$tmpARRAY_error = array($this->__oSocket);
    					$tmpINT_SocketNum = @socket_select($r=array(), $tmpARRAY_write, $tmpARRAY_error, 0, 10);
    					
    					// Controlla che il socket_select è riuscito
    					if ($tmpINT_SocketNum === FALSE) {
    						
    						// Se è fallito il select
    						$tmpINT_ConnStatus = 4;
    					}
    					
    					// Verifica se socket_select ha restituito un valore maggiore di zero
    					// se si procede a controllare se la connessione è riuscita o se si
    					// sono verificati errori
    					if ($tmpINT_ConnStatus === 0 AND $tmpINT_SocketNum > 0) {
    						if (count($tmpARRAY_write)) {	// Tutto è andato a buon fine
    							$tmpINT_ConnStatus = 1;
    						} else {						// Si è verificato un'errore
    							$tmpINT_ConnStatus = 2;
    						}
    					}
    					
    					// Nessun valore è stato ritornato di conseguenza controlla se il
    					// timeout per la connessione è stato superato
    					if ($tmpINT_ConnStatus == 0) {
    						
    						// Esegue il controllo
    						if ((time() - $this->__conn_starttime) > $this->__conn_timeout) {
    							$tmpINT_ConnStatus = 3;
    						}
    					}
    					
    					switch($tmpINT_ConnStatus) {
    						
    						case 1:		// Connessione Riuscita
    							
    							// Recupera i parametri di connessione dell'host remoto
    							socket_getpeername($this->__oSocket, $tmpSTR_addr, $tmpINT_port);
    							
    							// Imposta il nuovo stato
    							$this->state = S_SOCKET_CONNECTED;
    							
    							// Richiama la callback
    							$this->__manage_callbacks('connection_done', array($tmpSTR_addr,$tmpINT_port));
    							
    							echo "CONNESSIONE ESEGUITA!!!";
    							
    							break;
    							
    						case 2:		// Connessione Fallita
    							
    							// Imposta l'errore
    							
    							// Imposta il nuovo stato
    							
    							// Richiama la callback
    							echo "connessione fallita";
    							
    							break;
    							
    						case 3:		// Timeout di connessione
    							
    							// Imposta l'errore
    							
    							// Imposta il nuovo stato
    							
    							// Richiama la callback
    							echo "timeout di connessione";
    							
    							break;
    						
    						case 4:		// socket_select fallita
    							
    							// Imposta l'errore
    							
    							// Imposta il nuovo stato
    							
    							// Richiama la callback
    							echo "socket_select fallita";
    							
    							break;
    					}
    					
    					break;
    					
    				case S_SOCKET_CONNECTED:	// Controlla che la socket sia aperta,
    											// che non vi siano errori ed infine
    											// controlla se ci sono dati da leggere
    					
    					
    					
    					break;
    					
    				case S_SOCKET_LISTING:		// Essendo la socket in modalità
    											// listing resta in attesa e controlla
    											// quando vi sono socket da accettare
    					
    					break;
    					
    			}
    			
    		}
    		
    		// Imposta lo stato di connessione
    		function connect($remote_host, $remote_port, $timeout = 60) {
    			
    			// Avvia il tentativo di connessione
    			@socket_connect($this->__oSocket, $remote_host, $remote_port);
    			
    			// Imposta lo stato su CONNESSIONE IN CORSO
    			$this->state = S_SOCKET_CONNECTING;
    			
    			// Imposta la data di inizio connessione
    			$this->__conn_starttime = time();
    			
    			// Imposta il timeout di connessione
    			$this->__conn_timeout = $timeout;
    			
    		}
    		
    		// Chiude la connessione ed imposta lo stato di chiusura della socket
    		function close() {
    			
    			// Chiude la socket
    			@socket_close($this->__oSocket);
    			
    			// Imposta lo stato
    			$this->state = S_SOCKET_CLOSED;
    			
    		}
    		
    		// Imposta la porta e l'host locale
    		function bind($local_host, $local_port = 0) {
    			
    			
    			// Binda la socket sull'indirizzo e la porta passate
    			if ($local_port === 0) {
    				
    				// La porta non è stata passata e quindi non viene impostata
    				$res = @socket_bind($this->__oSocket, $local_host);
    			} else {
    				
    				// La posta è stata passata tra i parametri e quindi viene impostata
    				$res = @socket_bind($this->__oSocket, $local_host, $local_port);
    			}
    			
    			// Controlla se l'operazione è riuscita correttamente
    			if ($res === FALSE) {
    				
    				// Stampa a video l'errore
    				$this->__log('WARNING', 'Impossibile bindare la socket su ' . $local_host . (($local_port !== 0) ? ":{$local_port}" : '') . '! Errore: ' . socket_strerror(socket_last_error($this->__oSocket)), TRUE, TRUE);
    			}
    			
    		}
    		
    		// Scrive nella socket
    		function write() {}
    		
    		// Legge dalla socket
    		function read() {}
    		
    		// Imposta la socket in modalità listen
    		function listen() {}
    		
    		// Imposta le callbacks
    		function set_callback($callback_name, $callback_function) {}
    		
    		// Legge la stringa d'errore
    		function get_strerror($error_code) {}
    		
    		/*
    		 * PRIVATE FUNCTIONS
    		 */ 
    		
    		// Funzione per impostare l'errore
    		function __set_error($error_code) {
    			$this->__error_code = $error_code;
    		}
    		
    		// Funzione per stampare a video un LOG
    		function __log($level, $msg, $timestamp=TRUE, $die=FALSE) {
    			
    			// Controlla se deve aggiungere o meno il timestamp
    			if ($timestamp === TRUE) {
    				
    				// Log con timestamp
    				$tmpmsg = "[{$level}] [" . date('d/m/Y H:n:i') . "] {$msg}\n";
    			} else {
    				
    				// Log senza timestamp
    				$tmpmsg = "[{$level}] {$msg}\n";
    			}
    			
    			// Stampa a video il timestamp
    			echo $tmpmsg;
    			
    			// Controlla se è richiesta l'uscita
    			if ($die === TRUE) {
    				
    				// Se si esce
    				exit;
    			}
    			
    		}
    		
    		// Funzione per gestire le callbacks
    		function __manage_callbacks($callback_name, $params = array(), $return_result = FALSE) {
    			
    		}
    		
    	}
    	
    ?>
    serve per gestire in maniera TOTALMENTE asincrona, usando delle callbacks o eventi, le socket

    per utilizzare la classe...
    codice:
    <?php
    	require_once('Socket.class.php');
    	$clsSocket = &new clsSocket();
    	$clsSocket->bind('192.168.0.4', 80);
    	$clsSocket->connect('www.google.it', 80);
    	while (1) {
    		$clsSocket->doEvents();
    		if ($clsSocket->state = S_SOCKET_CONNECTED) {
    			break;
    		}
    	}
    	echo "Connesso a www.google.it:80\n";
    	$clsSocket->close();
    ?>
    ovviamente manca ancora un casino di codice, tra cui quello per gestire le callbacks, ma nel frattempo, qualcuno gli da un'occhiata per vedere se l'idea di base va bene?

    se vedete praticamente nel metodo doEvents leggo lo stato e mi comporto di conseguenza ^^

  2. #2
    ho chiesto troppo vero?

    almeno c'ho provato

  3. #3
    Aggiunta al thread in rilievo, tra le VARIE
    Addio Aldo, amico mio... [03/12/70 - 16/08/03]

  4. #4
    Scusa ma è incompleta...
    non era meglio che la finivi e poi la postavi?
    [ DarCas The Architect ]
    [ The DarCas Of Blog ]
    Chuck Norris riesce a trovare un pagliaio dentro a un ago
    :maLOL:

  5. #5
    Originariamente inviato da DarCas
    Scusa ma è incompleta...
    non era meglio che la finivi e poi la postavi?
    no xche siccome voglio che sia internalmente ben scritta ho bisogno di parareri ^^

    fare delle scelte di progettazione serie come ad esempio il sistema di gestione degli eventi comporta una struttura TOTALMENTE diversa e quindi devo scegliere cosa seguire

    per questo volevo dei pareri e anche per questo ho aperto un'altro thread con una domanda specifica

  6. #6
    ho PESANTEMENTE aggiornato la classe
    ancora manca del sistema di gestione delle callback xche sono ancora indeciso se usare per l'appunto le callback o l'estensione della classe.

    Ho aggiornato doEvents, inoltre ho centralizzato il sistema per il cambio dello stato e degli errori in modo da poter inserire un'apposita callback per quando si cambia stato o si verifica un'errore. Ho anche completato la funzione Write

    Manca ancora la funzione read ma non è un problema, xche prima devo completare doEvents, dato che read leggerà da un buffer interno alla classe e non dalla socket (e questo buffer verrà appunto riempito nel metodo doEvents)

    Ho definito nel TODO alcune nuove funzioni

    la funzione listen non farà altro che impostare in ascolto la socket e impostare lo stato

    qui c'è un codicillo di esempio

    codice:
    <?php
    	require_once('Socket.class.php');
    	$clsSocket = &new clsSocket();
    	$clsSocket->bind('192.168.0.4', 80);
    	$clsSocket->connect('www.google.it', 80);
    	
    	while (1) {
    		$clsSocket->doEvents();
    		if ($clsSocket->state = S_SOCKET_CONNECTED) {
    			break;
    		}
    	}
    	
    	echo "Connesso a www.google.it:80\n";
    	echo "Invio richiesta HTTP\n";
    	
    	$clsSocket->write("GET / HTTP/1.0\r\nHOST: www.google.it\r\n\r\n");
    	
    	$start = time();
    	while(($start+10)>time()) {
    		$clsSocket->doEvents();
    	}
    	
    	echo "Connessione a www.google.it:80 chiusa\n";
    	$clsSocket->close();
    ?>
    a breve, torno da un'assistenza, e posto uno zip
    xora è possibile inviare solo i dati, e non leggerli, e non ci sono ancora le callbacks, tanto che nel while controllo se la connessione avviene o meno in base allo stato

    cmq...ditemi che ne dite DD

  7. #7
    Originariamente inviato da daniele_dll
    serve per gestire in maniera TOTALMENTE asincrona
    Un lavoro interessante.
    Con la classe puoi chiamare (ora o quando l'avrai finita) un servizio o una funzione presente sul server con un thread principale e associare il compito dell'esecuzione della funzione ad un secondo thread indipendente che alla fine del lavoro richiama un metodo della tua classe leggibile dal primo thread?
    Saluti a tutti
    Riccardo

  8. #8
    Originariamente inviato da riccardone
    Un lavoro interessante.
    Con la classe puoi chiamare (ora o quando l'avrai finita) un servizio o una funzione presente sul server con un thread principale e associare il compito dell'esecuzione della funzione ad un secondo thread indipendente che alla fine del lavoro richiama un metodo della tua classe leggibile dal primo thread?
    uso un sistema asincrona proprio per non usare i thread ^^
    senno userei i thread e farei una classe molto meno flessibile

    ma non usare thread vuol dire anche non usare semafori, non usare lock vari, non usare memoria condivisa ( e quindi ipc ) e tante altre cose ^^

  9. #9
    Originariamente inviato da daniele_dll
    uso un sistema asincrona proprio per non usare i thread ^^
    Allora non ho capito cosa intendi per programmazione asincrona. Pazienza.
    Saluti a tutti
    Riccardo

  10. #10
    programmazione senza usare cicli all'interno dei singoli componenti o per la precisione programmare senza far si che i singoli componenti acquisiscano il completo controllo

    se guardi, la classe, non fa nulla, in nessun momento, solo il codice principale ha i cicli per le varie operazioni

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.