Controllo della connessione della presa Delphi. Delfi. Programmazione dei socket in Delphi. Invio e ricezione di dati complessi

Le prese (dalla presa (inglese) - connettore, presa) sono interfaccia software, che garantisce lo scambio di informazioni tra i processi.

Uno dei principali vantaggi della comunicazione tramite socket in una rete è la sua flessibilità. Il principio principale del lavoro con i socket è inviare una sequenza di byte a un altro computer, può essere un semplice messaggio di testo o un file.

È importante distinguere tra due tipi di prese: prese client , E prese del server .

Per lavorare con il tipo di socket "client" in Delphi, c'è un componente TClientSocket, puoi lavorare con socket "server" usando il componente TServerSocket.

Installazione dei componenti

Spesso i componenti TServerSocket e TClientSocket non sono inclusi nel pacchetto di installazione standard di Delphi, ma possono essere installati separatamente.

Vai alla scheda dei componenti "Internet" e controlla se i componenti TServerSocket e TClientSocket sono presenti lì, in caso contrario, installali. Vai al menu "Componente/Installa pacchetti", quindi fai clic sul pulsante "Aggiungi". Nella finestra di dialogo che si apre, devi trovare il file "dclsocketsXX.bpl" (si trova nella cartella bin, che si trova nella cartella con Delphi), dove XX è il numero di versione numerico del tuo Delphi. Individuare il file, fare clic su Apri, quindi fare clic su OK nella finestra Installa pacchetti. Ora, nella scheda "Internet" sono apparsi due componenti: TServerSocket e TClientSocket.

Utilizzo dei socket client (tClientSocket)

1) Definizione delle proprietà di Port e Host. Per una proprietà di connessione di successo porta E Ospite al componente TClientSocket devono essere assegnati dei valori. Nella proprietà Port, è necessario specificare il numero di porta per la connessione (1 - 65535, ma è preferibile prendere dall'intervallo 1001 - 65535, poiché i numeri fino a 1000 possono essere occupati dai servizi di sistema).

Ospite- nome host o indirizzo IP del computer a cui vuoi connetterti. Ad esempio, rus.delphi.com o 192.128.0.0.

2) Apertura di una presa. Considereremo un socket come una coda di caratteri trasmessi da un computer all'altro. Puoi aprire un socket chiamando il metodo aprire(componente TClientSocket) oppure assegnando un valore VERO proprietà Attivo. Qui sarebbe utile inserire un gestore di eccezioni in caso di connessione fallita.

3) Invio/ricezione dati.

4) Chiusura della presa. Al termine dello scambio di dati, è necessario chiudere il socket chiamando il metodo vicino componente TClientSocket o assegnando un valore Falso proprietà Attivo.

Proprietà di base del componente TClientSocket

Un'indicazione se la presa è aperta o chiusa. Aperto - Valore vero, chiuso - Valore falso. Disponibile per la registrazione.

Nome host a cui connettersi

L'indirizzo IP del computer a cui connettersi. A differenza di Host, qui è possibile specificare solo l'IP. La differenza è che se Host contiene un nome di computer letterale, l'IP verrà richiesto dal DNS

Il numero di porta del computer a cui connettersi (1-65535)

Tipo cliente

Contiene il tipo di trasferimento dati:

ctBlocking- trasmissione sincrona ( SuLeggi E Su Scrivi non funziona). Il tipo di connessione sincrona è adatto per lo scambio di dati in streaming;

ctNonBlocking- trasmissione asincrona (l'invio/la ricezione dei dati può essere effettuata utilizzando gli eventi SuLeggi E Su Scrivi)

Metodi di base del componente TClientSocket

Apre un socket (impostando la proprietà Active su True)

Chiude il socket (impostando la proprietà Active su False)

Principali eventi del componente TClientSocket

Su Connetti

Si verifica quando viene stabilita una connessione. Nel gestore è già possibile avviare l'autorizzazione o l'invio/ricezione dei dati

In connessione

Si verifica anche quando è connesso. Differisce da OnConnect in quanto la connessione non è stata ancora stabilita. Molto spesso utilizzato, ad esempio, per aggiornare lo stato

OnDisconnect

L'evento si verifica quando il socket viene chiuso dal programma, dal computer remoto oa causa di un errore

L'evento viene generato in caso di errore. Durante l'apertura del socket, questo evento non aiuterà a rilevare l'errore. Per evitare un messaggio di errore da Windows, è meglio occuparsi della gestione delle eccezioni interne inserendo le istruzioni aperte in un " provare..tranne »

Sulla ricerca

L'evento si verifica quando si tenta di ottenere un indirizzo IP dal DNS

L'evento si verifica quando un computer remoto ti invia dei dati. Quando si chiama OnRead, è possibile elaborare i dati ricevuti

L'evento viene generato quando al tuo programma è consentito scrivere dati nel socket

Questo articolo coprirà le proprietà e le funzioni di base Componenti Delfi: TClientSocket e TServerSocket - utilizzati per lavorare con la rete utilizzando il protocollo TCP\IP.

Attenzione! Se stai utilizzando una versione di Delphi superiore alla 6.0, devi prima installare Sockets Components, in tutte le versioni di Delphi questo viene fatto come segue:

  • Vai alla finestra di dialogo Installa pacchetti...: (Menu principale) Componente -> Installa pacchetti;
  • Clicca sul pulsante Aggiungi…, dopodiché troviamo la cartella Bin del tuo Delphi (es: C:\Program Files\Borland\Delphi 7\bin , oppure C:\Program Files\Embarcadero\RAD Studio\7.0\Bin);
  • Nella cartella Bin trovata, stiamo già cercando un file dclsocket [numeri qui].bpl, fare clic su OK;
  • Siamo felici, perché ora abbiamo due meravigliosi componenti TServerSocket e TClientSocket nella scheda del pannello dei componenti della scheda Internet.

Quando si sviluppano applicazioni di rete, lo sviluppo di solito inizia sempre dal server (ovviamente, se si dispone di un team, i progettisti front-end possono iniziare a lavorare sul client). Per implementare il server, sorprendentemente, è necessario utilizzare TServerSocket.

Proprietà di base:

  • Attivo– campo di tipo booleano, quando impostato a true – il server è avviato, può essere utilizzato sia assegnando valori specifici, sia chiamando il ServerSocket1.Open (… Active:=true;) o il ServerSocket1.Close (… Active:=false) funzioni.
  • porta- la porta su cui il server ascolterà (riceverà client), qualsiasi valore non occupato da altri server nel sistema all'interno dell'intervallo numero intero.

Eventi principali:

  • In ascolto- chiamato quando il server è impostato in modalità di ascolto, può essere utilizzato quando è necessario determinare l'ora di avvio effettiva del server.
  • OnClientLeggi– viene chiamato al momento della ricezione dei dati dal client.
  • OnClientError
  • OnClientConnect- Chiamato quando un nuovo client si unisce al server.
  • OnClientDisconnect- l'evento opposto all'evento, OnClientConnect

ogni funzione evento ha un attributo Presa: TCustomWinSocket, un puntatore all'oggetto socket con cui ci troviamo questo momento lavoro, se dobbiamo rispondere a qualcosa o fare qualcosa con il cliente che ha attivato l'evento, dobbiamo usare questo particolare oggetto, in tutti gli altri casi usiamo ServerSocket1.Socket, la situazione è simile con il componente client.

Proprietà e funzioni di sola lettura:

  • – restituisce il numero di connessioni attive.
  • ServerSocket1.Socket.Connections– un array di oggetti di tipo TCustomWinSocket, un array di tutti gli oggetti associati ai client, il conteggio dell'indice parte da 0, la lunghezza dell'array è pari a ServerSocket1.Socket.ActiveConnections.
  • Funzioni e proprietà che si applicano agli elementi dell'array ServerSocket1.Socket.Connections e all'attributo Socket passato alla funzione evento del server:
  • Socket.LocalHost
  • Socket.LocalAddress– restituisce l'IP del server.
  • Socket.RemoteHost
  • Socket.RemoteAddress– restituisce l'IP del client.
  • Socket.ReceiveText- restituisce un sms ricevuto dal client, dopodiché azzera il buffer, può essere utilizzato solo 1 volta, per 1 ricezione.
  • Socket.SendText(Testo)– invia un messaggio di testo di tipo Testo al client corda.

Per il componente TClientSocket, tutto è quasi uguale, solo il contrario + la principale differenza visiva tra il server e il client, il server nel sistema può essere avviato 1 per 1 valore di porta, solo la RAM ti limita nel numero di clienti.

Proprietà di base:

  • Attivo– campo di tipo booleano, quando impostato a true – il client tenta di connettersi al server, può essere utilizzato sia assegnando valori specifici, sia chiamando il ClientSocket1.Open (… Active:=true;) o il ClientSocket1.Close (… Active :=falso) funzioni .
  • porta– porta sulla quale il client può connettersi al server, qualsiasi valore all'interno dell'intervallo numero intero.
  • Indirizzo– Indirizzo IPv4 del tipo di server corda modello 255.255.255.255 a cui si connetterà il client.

Eventi principali:

  • SuLeggi– chiamato quando i dati vengono ricevuti dal nord.
  • OnError- Chiamato quando si verifica un errore nel trasferimento dei dati.
  • In connessione- Chiamato quando il client si connette al server.
  • OnDisconnect- l'evento opposto all'evento, In connessione, chiamato durante una disconnessione del client dal server.

Proprietà e funzioni di sola lettura:

  • ClientSocket1.Socket.SendText() corda
  • Socket.LocalHost– restituisce il nome del client sulla rete.
  • Socket.LocalAddress– restituisce l'IP del client.
  • Socket.RemoteHost– restituisce il nome del server sulla rete.
  • Socket.RemoteAddress– restituisce l'IP del server.
  • Socket.ReceiveText– restituisce un SMS ricevuto dal server, dopodiché azzera il buffer, può essere utilizzato solo 1 volta, per 1 ricezione.
  • Socket.SendText(Testo)– invia un messaggio di testo di tipo Testo al server corda.

Le informazioni fornite sono sufficienti per implementare una piccola chat sul server che soddisfi termine di paragone: internet_sockets.doc (Word Doc 97-2003, 26,5 Kb).

Questo articolo è stato scritto domenica 10 ottobre 2010 alle 1:24 nella sezione . Puoi iscriverti agli aggiornamenti dei commenti all'articolo -. Puoi


introduzione


Questo articolo riguarda la creazione di applicazioni client/server basate su socket in Borland Delphi ("socket" - nidi). A differenza del precedente articolo sul tema dei socket, qui analizzeremo la creazione di applicazioni server.

Va notato subito che per la coesistenza di applicazioni client e server separate non è necessario disporre di più computer. È sufficiente averne solo uno su cui è possibile eseguire contemporaneamente sia il server che il client. In questo caso, è necessario utilizzare il nome host come nome del computer a cui ci si vuole connettere. localhost o indirizzo IP - 127.0.0.1 .

Quindi iniziamo con la teoria. Se sei un praticante convinto (e non riesci a vedere alcun algoritmo con i tuoi occhi), allora dovresti saltare questa sezione.

Algoritmo del server socket


Cosa fa un server socket?.. Come funziona?.. Un server basato sul protocollo socket consente di servire più client contemporaneamente. Inoltre, puoi specificare tu stesso un limite al loro numero (o rimuovere del tutto questo limite, come avviene per impostazione predefinita). Per ogni client connesso, il server apre un socket separato, attraverso il quale è possibile scambiare dati con il client. Anche un'ottima soluzione è creare un processo separato (Thread) per ogni connessione.

Quello che segue è un esempio di come funziona un server socket nelle applicazioni Delphi:

Analizziamo lo schema in modo più dettagliato:

  • Definizione delle proprietà in Port e ServerType - affinché i client possano connettersi normalmente al server, la porta utilizzata dal server deve corrispondere esattamente alla porta utilizzata dal client (e viceversa). La proprietà ServerType determina il tipo di connessione (vedi sotto per i dettagli);
  • apertura presa - Apertura di un socket e della porta specificata. Qui viene eseguito l'avvio automatico dell'attesa per la connessione dei client ( Ascoltare);
  • Connettere un cliente e scambiare dati con lui - qui il client si connette e i dati vengono scambiati con esso. Puoi saperne di più su questa fase più avanti in questo articolo e nell'articolo sui socket (lato client);
  • Disabilitare un client - Qui il client si disconnette e la sua connessione socket al server viene chiusa;
  • Chiusura del server e del socket - Al comando dell'amministratore, il server termina il suo lavoro, chiudendo tutti i canali socket aperti e interrompendo l'attesa delle connessioni client.

Va notato che i punti 3-4 vengono ripetuti molte volte, ad es. questi elementi vengono eseguiti per ogni nuova connessione client.

Nota : C'è pochissima documentazione sui socket in Delphi al momento, quindi se vuoi studiare questo argomento il più a fondo possibile, allora ti consiglio di consultare la letteratura e la documentazione elettronica sui sistemi Unix/Linux - lì Molto La teoria del lavoro con le prese è ben descritta. Inoltre, ci sono molti esempi di applicazioni socket per questi sistemi operativi (ma soprattutto in C/C++ e Perl).

Breve descrizione del componente TServerSocket


Qui faremo conoscenza principale proprietà, metodi ed eventi del componente TServerSocket.

Proprietà

PRESA - la classe TServerWinSocket, attraverso la quale si ha accesso ai canali socket aperti. Successivamente, considereremo questa proprietà in modo più dettagliato, perché. è, infatti, uno dei principali. Tipo: TServerWinSocket ;
Tipo di server - tipo di server. Può assumere uno dei due valori: stNonBloccante- lavoro sincrono con i socket client. Con questo tipo di server, puoi lavorare con i client tramite eventi OnClientLeggi E OnClientWrite. stThreadBlocking- tipo asincrono. Viene creato un processo separato (thread) per ogni canale socket client. Tipo: TServerType ;
ThreadCacheSize - il numero di processi client (Thread) che verranno memorizzati nella cache dal server. Qui devi selezionare il valore medio in base al carico sul tuo server. La memorizzazione nella cache avviene per non creare ogni volta un processo separato e non per uccidere il socket chiuso, ma per lasciarli per un ulteriore utilizzo. Tipo: Numero intero ;
Attivo - un indicatore se il server è attualmente attivo o meno. Questo è, infatti, il valore VERO indica che il server è in esecuzione e pronto a ricevere client e Falso- il server è spento. Per avviare il server, devi solo impostare questa proprietà su VERO. Tipo: Booleano ;
porta - numero di porta per stabilire connessioni con i client. La porta sul server e sui client deve essere la stessa. Si consigliano valori da 1025 a 65535, come da 1 a 1024 - può essere occupato dal sistema. Tipo: Numero intero ;
Servizio - una stringa che definisce il servizio ( ftp, http, pop, ecc.) la cui porta verrà utilizzata. Questo è una sorta di libro di riferimento per abbinare i numeri di porta a vari protocolli standard. Tipo: corda ;

aprire - Avvia il server. Essenzialmente, questo comando è identico all'assegnazione di un valore VERO proprietà Attivo;
vicino - Arresta il server. Essenzialmente, questo comando è identico all'assegnazione di un valore Falso proprietà Attivo.

OnClientConnect - si verifica quando un client ha stabilito una connessione socket ed è in attesa di una risposta dal server ( SuAccetta);
OnClientDisconnect - si verifica quando il client si è disconnesso dal canale socket;
OnClientError - si verifica quando l'operazione corrente non è riuscita, ad es. C'è stato un errore;
OnClientLeggi - si verifica quando il client ha inviato alcuni dati al server. È possibile accedere a questi dati tramite il parametro passato Presa: TCustomWinSocket;
OnClientWrite - si verifica quando il server può inviare dati al client sul socket;
OnGetSocket - nel gestore di questo evento, puoi modificare il parametro ClientSocket;
OnGetThread - nel gestore di questo evento è possibile definire un processo univoco (Thread) per ogni singolo canale client impostando il parametro SocketThread la sottoattività desiderata TServerClientThread;
OnThreadStart , OnThreadEnd - si verifica quando una sottoattività (processo, Thread) si avvia o si interrompe, rispettivamente;
SuAccetta - si verifica quando il server accetta un client o rifiuta una connessione;
In ascolto - Si verifica quando il server entra nella modalità di attesa della connessione dei client.


TServerSocket.Socket(TServerWinSocket)


Quindi, come può un server inviare dati a un client? E la ricezione dei dati? Fondamentalmente se lavori attraverso gli eventi OnClientLeggi E OnClientWrite, è possibile comunicare con il client tramite il parametro ClientSocket (TCustomWinSocket). Puoi leggere come lavorare con questa classe nell'articolo sui socket client. l'invio/l'invio di dati tramite questa classe è simile: metodi (Invia/Ricevi)(Testo,Buffer,Stream). Anche quando si lavora con TServerSocket.Socket. Tuttavia, da quando Dal momento che stiamo considerando un server, dovrebbero essere evidenziate alcune proprietà e metodi utili:

  • Connessioni attive (Numero intero) - numero di client connessi;
  • ActiveThreads (Numero intero) è il numero di processi in esecuzione;
  • Connessioni (vettore) è un array costituito da singole classi TClientWinSocket per ogni client connesso. Ad esempio, questo comando:
    ServerSocket1.Socket.Connections.SendText("Ciao!");
    invia un messaggio "Ciao!" al primo client connesso. Anche i comandi per lavorare con gli elementi di questo array sono (Send/Receive)(Text,Buffer, Stream);
  • Thread inattivi (Numero intero) è il numero di processi liberi. Tali processi vengono memorizzati nella cache dal server (vedere ThreadCacheSize);
  • indirizzo locale, localhost, porto locale- rispettivamente - indirizzo IP locale, nome host, porta;
  • indirizzo remoto, Host remoto, porto remoto- rispettivamente - indirizzo IP remoto, nome host, porta;
  • Metodi serratura E sbloccare- rispettivamente, blocco e sblocco di una presa.

Pratica ed esempi


Ora considera quanto sopra esempio specifico. Puoi scaricare fonti già pronte facendo clic su .

Quindi, diamo un'occhiata a un ottimo esempio di lavoro con TServerSocket (questo esempio è l'aiuto più visivo per l'apprendimento di questo componente). Il codice sorgente di seguito mostra la registrazione di tutti gli eventi importanti del server, oltre alla possibilità di ricevere e inviare messaggi di testo:

Esempio 1 Registrazione e studio lavoro del server, invio/ricezione di messaggi tramite socket

(... Ecco l'intestazione del file e la definizione del form TForm1 e la sua istanza Form1)
(Vedi fonte completa)
procedura TForm1.Button1Click(Sender: TObject); inizio (Definiamo la porta e avviamo il server) ServerSocket1.Porta:= 1025; (Il metodo Insert inserisce una stringa nell'array nella posizione specificata) Memo2.Lines.Insert(0,"Avvio del server"); ServerSocket1.Open; FINE; procedura TForm1.Button2Click(Sender: TObject); inizio (Ferma il server) ServerSocket1.Active:= Falso; Memo2.Lines.Insert(0,"Server arrestato"); FINE; procedura TForm1.ServerSocket1Listen(Sender: TObject; Socket: TCustomWinSocket); inizio (Qui il server "ascolta" sul socket per i client) Memo2.Lines.Insert(0,"Ascolto sulla porta "+IntToStr(ServerSocket1.Port)); FINE; procedura TForm1.ServerSocket1Accept(Sender: TObject; Socket: TCustomWinSocket); inizio (Qui il server accetta il client) Memo2.Lines.Insert(0,"Connessione client accettata"); FINE; procedura TForm1.ServerSocket1ClientConnect(Mittente: TObject; Socket: TCustomWinSocket); inizio (Qui il client si connette) Memo2.Lines.Insert(0,"Client connesso"); FINE; procedura TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); inizio (Qui il client si disconnette) Memo2.Lines.Insert(0,"Client disconnesso"); FINE; procedura TForm1.ServerSocket1ClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); inizio (Si è verificato un errore - stampa il suo codice) Memo2.Lines.Insert(0,"Errore client. Code = "+IntToStr(ErrorCode)); FINE; procedura TForm1.ServerSocket1ClientRead(Mittente: TObject; Socket: TCustomWinSocket); inizio (È stato ricevuto un messaggio dal cliente - lo visualizziamo in Memo1) Memo2.Lines.Insert(0,"Messaggio ricevuto dal client"); Memo1.Lines.Insert(0,"> "+Socket.ReceiveText); FINE; procedura TForm1.ServerSocket1ClientWrite(Mittente: TObject; Socket: TCustomWinSocket); inizio (Ora puoi inviare dati al socket) Memo2.Lines.Insert(0,"Ora puoi scrivere sul socket"); FINE; procedure TForm1.ServerSocket1GetSocket(Sender: TObject; Socket: Integer; var ClientSocket: TServerClientWinSocket); begin Memo2.Lines.Insert(0,"Ottieni socket"); FINE; procedura TForm1.ServerSocket1GetThread(Mittente: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); begin Memo2.Lines.Insert(0,"Get Thread"); FINE; procedura TForm1.ServerSocket1ThreadEnd(Mittente: TObject; Discussione: TServerClientThread); begin Memo2.Lines.Insert(0,"Fine filo"); FINE; procedura TForm1.ServerSocket1ThreadStart(Sender: TObject; Thread: TServerClientThread); begin Memo2.Lines.Insert(0,"Inizio discussione"); FINE; procedura TForm1.Button3Click(Sender: TObject); var i: numero intero; inizio (Invia a TUTTI i clienti un messaggio da Edit1) per i:= 0 a ServerSocket1.Socket.ActiveConnections-1 inizia ServerSocket1.Socket.Connections[i].SendText(Edit1.Text); FINE; Memo1.Linee.Inserisci(0,"

Tecniche per lavorare con TServerSocket (e solo socket)


Memorizzazione di dati univoci per ogni cliente.


Sicuramente, se il tuo server servirà molti client, dovrai memorizzare alcune informazioni per ciascun client (nome, ecc.) E con l'associazione di queste informazioni al socket di questo client. In alcuni casi, eseguire tutto questo manualmente (associazione a un handle di socket, array di client, ecc.) non è molto conveniente. Pertanto, esiste una proprietà speciale per ogni socket: Dati. In effetti, Data è solo un puntatore. Pertanto, quando si scrivono i dati del client in questa proprietà, prestare attenzione e seguire le regole per lavorare con i puntatori (allocazione della memoria, inferenza del tipo, ecc.)!

Invio di file tramite un socket.


Qui esamineremo l'invio di file su un socket (come richiesto da JINX) :-). Quindi, come si invia un file tramite un socket? Molto semplice! Devi solo aprire questo file come flusso di file (TFileStream) e inviarlo tramite socket (SendStream)! Vediamolo con un esempio:

Va notato che il metodo sendstream utilizzato non solo dal server, ma anche dal client ( ClientSocket1.Socket.SendStream(srcfile))

Perché è possibile combinare più blocchi in uno durante la trasmissione?


Questo è richiesto anche da JINX :-). Molte grazie a lui per questo! Quindi, in primo luogo, va notato che i dati inviati tramite il socket non solo possono essere combinati in un blocco, ma anche separati in più blocchi. Il fatto è che un socket è un flusso normale, ma a differenza, diciamo, di un flusso di file (TFileStream), trasferisce i dati più lentamente (capisci: rete, traffico limitato, ecc.). Ecco perché due comandi:
ServerSocket1.Socket.Connections.SendText("Ciao, ");
ServerSocket1.Socket.Connections.SendText("mondo!");
sono completamente identici a un comando:
ServerSocket1.Socket.Connections.SendText("Ciao mondo!");

Ed è per questo che, se invii un file, diciamo, 100 Kb, attraverso il socket, la persona a cui hai inviato questo blocco riceverà diversi blocchi con dimensioni che dipendono dal traffico e dal carico della linea. Inoltre, le dimensioni non devono essere le stesse. Ne consegue che per ricevere un file o qualsiasi altro dato grande taglia, Dovresti prendere blocchi di dati e poi combinarli in un tutto (e salvarli, ad esempio, in un file). Un'ottima soluzione a questo problema è lo stesso flusso di file - TFileStream (o un flusso in memoria - TMemoryStream). È possibile ricevere particelle di dati dal socket tramite l'evento OnRead (OnClientRead), utilizzando il metodo universale RiceviBuf. È possibile determinare la dimensione del blocco risultante utilizzando il metodo Lunghezza ricezione. Puoi anche utilizzare un flusso socket (vedi l'articolo TClientSocket). Ed ecco un piccolo esempio (approssimativo):

Come monitorare una presa


La questione è complessa e richiede una lunga riflessione. Per ora, noterò solo che puoi sempre monitorare il socket creato dal tuo programma :-). I socket (come la maggior parte degli oggetti in Windows) hanno il proprio handle (handle), scritto nella proprietà Handle. Quindi, avendo appreso questo descrittore, puoi controllare liberamente qualsiasi socket (anche quelli creati dal programma di qualcun altro)! Tuttavia, molto probabilmente dovrai utilizzare le funzioni WinAPI Sockets per monitorare il socket di qualcun altro.


Questo articolo mostra i trucchi di base per lavorare con il componente TServerSocket in Delphi e alcuni trucchi generali per comunicare sui socket. Se hai domande, inviamele via e-mail: [e-mail protetta], e ancora meglio - scrivi nel forum di questo sito (Delphi. Domande generali), in modo che altri utenti possano vedere la tua domanda e provare a rispondere!

Karik Nikolaj ( nitro). Regione di Mosca, Zhukovsky

Questo articolo riguarda la creazione di applicazioni client/server basate su socket in Borland Delphi. A differenza del precedente articolo sul tema dei socket, qui analizzeremo la creazione di applicazioni server.
Va notato subito che per la coesistenza di applicazioni client e server separate non è necessario disporre di più computer. È sufficiente averne solo uno su cui è possibile eseguire contemporaneamente sia il server che il client. In questo caso, è necessario utilizzare il nome host localhost o l'indirizzo IP - 127.0.0.1 come nome del computer a cui si desidera connettersi.
Quindi iniziamo con la teoria. Se sei un praticante convinto (e non riesci a vedere alcun algoritmo con i tuoi occhi), allora dovresti saltare questa sezione.
Algoritmo del server socket
Cosa fa un server socket?.. Come funziona?.. Un server basato sul protocollo socket consente di servire più client contemporaneamente. Inoltre, puoi specificare tu stesso un limite al loro numero (o rimuovere del tutto questo limite, come avviene per impostazione predefinita). Per ogni client connesso, il server apre un socket separato, attraverso il quale è possibile scambiare dati con il client. Anche un'ottima soluzione è creare un processo separato (Thread) per ogni connessione.
Quello che segue è un esempio di come funziona un server socket nelle applicazioni Delphi:

Diamo un'occhiata allo schema più in dettaglio: · Definizione delle proprietà Port e ServerType - affinché i client possano connettersi normalmente al server, la porta utilizzata dal server deve corrispondere esattamente alla porta utilizzata dal client (e viceversa ). La proprietà ServerType determina il tipo di connessione (vedi sotto per i dettagli); · Socket aperto - socket aperto e porta specificata. Qui viene eseguito l'avvio automatico dell'attesa per la connessione dei client (Ascolta); · Connessione di un cliente e scambio di dati con lui - qui un cliente è connesso e i dati vengono scambiati con lui. Puoi saperne di più su questa fase più avanti in questo articolo e nell'articolo sui socket (lato client); · Client Disconnect - Qui il client è disconnesso e la sua connessione socket al server è chiusa; · Chiusura del server e del socket: al comando dell'amministratore, il server si spegne, chiudendo tutti i canali socket aperti e interrompendo l'attesa delle connessioni client.
Va notato che i punti 3-4 vengono ripetuti molte volte, ad es. questi elementi vengono eseguiti per ogni nuova connessione client.
Nota: al momento c'è pochissima documentazione sui socket in Delphi, quindi se vuoi studiare questo argomento il più a fondo possibile, ti consiglio di consultare la letteratura e la documentazione elettronica sui sistemi Unix / Linux - la teoria del lavoro con prese è molto ben descritto lì. Inoltre, ci sono molti esempi di applicazioni socket per questi sistemi operativi (ma soprattutto in C/C++ e Perl).
Breve descrizione del componente TServerSocket
Qui faremo conoscenza con le principali proprietà, metodi ed eventi del componente.
Proprietà
Socket - Classe TServerWinSocket attraverso la quale si ha accesso ai canali socket aperti. Successivamente, considereremo questa proprietà in modo più dettagliato, perché. è, infatti, uno dei principali. Tipo: TServerWinSocket;
ServerType: tipo di server. Può assumere uno dei due valori: stNonBlocking: lavoro sincrono con i socket client. Con questo tipo di server è possibile lavorare con i client tramite gli eventi OnClientRead e OnClientWrite. stThreadBlocking è un tipo asincrono. Viene creato un processo separato (thread) per ogni canale socket client. Tipo: TServerType;
ThreadCacheSize: il numero di processi client (Thread) che verranno memorizzati nella cache dal server. Qui devi selezionare il valore medio in base al carico sul tuo server. La memorizzazione nella cache avviene per non creare ogni volta un processo separato e non per uccidere il socket chiuso, ma per lasciarli per un ulteriore utilizzo. Tipo: numero intero;
Attivo: un indicatore del fatto che il server sia attualmente attivo o meno. Cioè, infatti, il valore True indica che il server è in esecuzione e pronto a ricevere client e False: il server è spento. Per avviare il server, devi solo impostare questa proprietà su True. Tipo: booleano
Porta - numero di porta per stabilire connessioni con i client. La porta sul server e sui client deve essere la stessa. Si consigliano valori da 1025 a 65535, come da 1 a 1024 - può essere occupato dal sistema. Tipo: numero intero;
Servizio: una stringa che specifica il servizio (ftp, http, pop, ecc.) di cui verrà utilizzata la porta. Questo è una sorta di libro di riferimento per abbinare i numeri di porta a vari protocolli standard. Tipo: stringa
Metodi
Apri: avvia il server. In sostanza, questo comando è identico all'impostazione del valore True nella proprietà Active;
Chiudi - Arresta il server. In sostanza, questo comando è identico all'impostazione del valore False nella proprietà Active.
Eventi
OnClientConnect - si verifica quando il client ha stabilito una connessione socket ed è in attesa della risposta del server (OnAccept);
OnClientDisconnect: generato quando un client si è disconnesso da un canale socket.
OnClientError - Generato quando l'operazione corrente non è riuscita, ad es. C'è stato un errore;
OnClientRead - attivato quando il client ha inviato alcuni dati al berver. È possibile accedere a questi dati tramite il parametro Socket fornito: TCustomWinSocket;
OnClientWrite - si verifica quando il server può inviare dati al client sul socket;
OnGetSocket: in questo gestore eventi è possibile modificare il parametro ClientSocket;
OnGetThread: nel gestore di questo evento, è possibile definire un processo univoco (Thread) per ogni canale client separato assegnando la sottoattività TServerClientThread richiesta al parametro SocketThread;
OnThreadStart, OnThreadEnd - si verifica quando una sottoattività (processo, Thread) viene avviata o arrestata, rispettivamente;
OnAccept - attivato quando il server accetta o nega una connessione a un client;
OnListen - Generato quando il server è in attesa che i client si connettano.
TServerSocket.Socket(TServerWinSocket)
Quindi, come può un server inviare dati a un client? E la ricezione dei dati? Fondamentalmente, se lavori tramite gli eventi OnClientRead e OnClientWrite, puoi comunicare con il client tramite il parametro ClientSocket (TCustomWinSocket). Puoi leggere come lavorare con questa classe nell'articolo sui socket client. l'invio/l'invio di dati tramite questa classe è simile: metodi (Invia/Ricevi)(Testo,Buffer,Stream). Anche quando si lavora con TServerSocket.Socket. Tuttavia, da quando qui stiamo considerando un server, dovrebbero essere evidenziate alcune proprietà e metodi utili: ActiveConnections (Integer) - il numero di client connessi; ActiveThreads (Integer): il numero di processi in esecuzione; ·Connessioni (array) - un array costituito da classi TClientWinSocket separate per ciascun client connesso. Ad esempio, il seguente comando: ServerSocket1.Socket.Connections.SendText("Hello!"); Invia un messaggio "Hello!" al primo client connesso. Anche i comandi per lavorare con gli elementi di questo array sono (Send/Receive)(Text,Buffer, Stream); ·IdleThreads (Integer) - il numero di processi inattivi. Tali processi vengono memorizzati nella cache dal server (vedere ThreadCacheSize); LocalAddress, LocalHost, LocalPort - rispettivamente - indirizzo IP locale, nome host, porta; ·RemoteAddress, RemoteHost, RemotePort - rispettivamente - indirizzo IP remoto, nome host, porta; ·Metodi Lock e UnLock - rispettivamente, blocco e sblocco di una presa.
Pratica ed esempi
Ora diamo un'occhiata a quanto sopra con un esempio specifico. Puoi scaricare fonti già pronte facendo clic qui.
Quindi, diamo un'occhiata a un ottimo esempio di lavoro con TServerSocket (questo esempio è l'aiuto più visivo per l'apprendimento di questo componente). Le fonti seguenti dimostrano la registrazione di tutti gli eventi importanti del server, oltre alla possibilità di ricevere e inviare messaggi di testo:
Esempio 1. Registrazione e studio del lavoro del server, invio / ricezione di messaggi tramite socket.

(... Ecco l'intestazione del file e la definizione del form TForm1 e la sua istanza Form1)

(Vedi la fonte completa qui)

procedura TForm1.Button1Click (Mittente: TObject ) ;

inizio

(Definiamo la porta e avviamo il server)

ServerSocket1.Port := 1025 ;

(Il metodo Insert inserisce una stringa nell'array nella posizione specificata)

Memo2.Lines .Insert (0 ,"Server in avvio" );

ServerSocket1.Open ;

FINE ;

procedura TForm1.Button2Click (Mittente: TObject ) ;

inizio

(Ferma il server)

ServerSocket1.Active := Falso ;

Memo2.Lines .Insert (0 ,"Server arrestato" );

FINE ;

procedura TForm1.ServerSocket1Listen(Sender: TObject ;

Socket: TCustomWinSocket);

inizio

(Qui il server "ascolta" sul socket per i client)

Memo2.Lines .Insert (0 ,"Ascolto sulla porta" +IntToStr (ServerSocket1.Port ) );

FINE ;

procedura TForm1.ServerSocket1Accept(Sender: TObject ;

Socket: TCustomWinSocket);

inizio

(Qui il server accetta il client)

Memo2.Lines .Insert (0 ,"Connessione client accettata" );

FINE ;

procedura TForm1.ServerSocket1ClientConnect(Mittente: TObject ;

Socket: TCustomWinSocket);

inizio

(Qui il client si connette)

Memo2.Lines .Insert (0 ,"Client connesso" );

FINE ;

procedura TForm1.ServerSocket1ClientDisconnect(Sender: TObject ;

Socket: TCustomWinSocket);

inizio

(Qui il client si disconnette)

Memo2.Lines .Insert (0 ,"Client disconnesso" );

FINE ;

procedura TForm1.ServerSocket1ClientError (Sender: TObject ;

Presa: TCustomWinSocket; ErrorEvent: TErrorEvent;

var ErrorCode: numero intero);

inizio

(Si è verificato un errore - stampa il suo codice)

Memo2.Lines .Insert (0 ,"Errore client. Code = " +IntToStr (ErrorCode) ) ;

FINE ;

procedura TForm1.ServerSocket1ClientRead(Mittente: TObject ;

Socket: TCustomWinSocket);

inizio

(È stato ricevuto un messaggio dal cliente - lo visualizziamo in Memo1)

Memo2.Linee .Inserisci (0 , "Messaggio ricevuto dal cliente") ;

Memo1.Lines .Insert (0 ,"> " +Socket.ReceiveText );

FINE ;

procedura TForm1.ServerSocket1ClientWrite(Mittente: TObject ;

Socket: TCustomWinSocket);

inizio

(Ora puoi inviare dati al socket)

Memo2.Lines .Insert (0 ,"Ora puoi scrivere sul socket" );

FINE ;

procedura TForm1.ServerSocket1GetSocket (Sender: TObject ; Socket: Integer ;

var ClientSocket: TServerClientWinSocket) ;

inizio

Memo2.Lines .Insert (0 ,"Ottieni socket" );

FINE ;

procedura TForm1.ServerSocket1GetThread(Sender: TObject ;

ClientSocket: TServerClientWinSocket;

varSocketThread: TServerClientThread) ;

inizio

Memo2.Lines .Insert (0 ,"Get Thread" ) ;

FINE ;

procedura TForm1.ServerSocket1ThreadEnd (Mittente: TObject ;

inizio

Memo2.Lines .Insert (0 ,"Fine filo" ) ;

FINE ;

procedura TForm1.ServerSocket1ThreadStart(Sender: TObject ;

Discussione: TServerClientThread) ;

inizio

Memo2.Lines .Insert (0 ,"Inizio discussione" );

FINE ;

procedura TForm1.Button3Click (Mittente: TObject ) ;

var i: intero ;

inizio

(Invia a TUTTI i clienti un messaggio da Edit1)

for i:= 0 a ServerSocket1.Socket.ActiveConnections -1 iniziano

ServerSocket1.Socket .Connections [i] .SendText (Edit1.Text ) ;

FINE ;

Memo1.Lines .Insert(0 ,"< " +Edit1.Text ) ;

FINE ;

Inoltre, non considereremo più esempi, ma metodi per lavorare con TServerSocket.
Tecniche per lavorare con TServerSocket (e solo socket)
Memorizzazione di dati univoci per ogni cliente.
Sicuramente, se il tuo server servirà molti client, dovrai memorizzare alcune informazioni per ciascun client (nome, ecc.) E con l'associazione di queste informazioni al socket di questo client. In alcuni casi, eseguire tutto questo manualmente (associazione a un handle di socket, array di client, ecc.) non è molto conveniente. Pertanto, per ogni socket esiste una proprietà speciale: i dati. In effetti, Data è solo un puntatore. Pertanto, quando si scrivono i dati del client in questa proprietà, prestare attenzione e seguire le regole per lavorare con i puntatori (allocazione della memoria, inferenza del tipo, ecc.)!
Invio di file tramite un socket.
Qui esamineremo l'invio di file su un socket (come richiesto da JINX) :-). Quindi, come si invia un file tramite un socket? Molto semplice! Devi solo aprire questo file come flusso di file (TFileStream) e inviarlo tramite socket (SendStream)! Vediamolo con un esempio:

(Invio di file tramite socket)

procedura SendFileBySocket(nomefile: string ) ;

var srcfile: TFileStream;

inizio

(Apri file nome file)

Srcfile:= TFileStream.Create (nomefile,fmOpenRead) ;

(Invialo al primo client connesso)

ServerSocket1.Socket .Connections [ 0 ] .SendStream(srcfile) ;

(Chiudi il file)

Srcfile.Free ;

FINE ;

Va notato che il metodo SendStream viene utilizzato non solo dal server, ma anche dal client (ClientSocket1.Socket.SendStream(srcfile))
Perché è possibile combinare più blocchi in uno durante la trasmissione?
Questo è richiesto anche da JINX :-). Molte grazie a lui per questo! Quindi, in primo luogo, va notato che i dati inviati tramite il socket non solo possono essere combinati in un blocco, ma anche separati in più blocchi. Il fatto è che un socket è un flusso normale, ma a differenza, diciamo, di un flusso di file (TFileStream), trasferisce i dati più lentamente (capisci: rete, traffico limitato, ecc.). Ecco perché due comandi:
ServerSocket1.Socket.Connections.SendText("Ciao, ");
ServerSocket1.Socket.Connections.SendText("mondo!");
sono completamente identici a un comando:
ServerSocket1.Socket.Connections.SendText("Ciao mondo!");
Ed è per questo che, se invii un file, diciamo, 100 Kb, attraverso il socket, la persona a cui hai inviato questo blocco riceverà diversi blocchi con dimensioni che dipendono dal traffico e dal carico della linea. Inoltre, le dimensioni non devono essere le stesse. Ne consegue che per ricevere un file o qualsiasi altro dato di grandi dimensioni, è necessario ricevere blocchi di dati e quindi combinarli in un insieme (e salvare, ad esempio, in un file). Un'ottima soluzione a questo problema è lo stesso flusso di file - TFileStream (o un flusso in memoria - TMemoryStream). È possibile ricevere particelle di dati dal socket tramite l'evento OnRead (OnClientRead), utilizzando il metodo universale ReceiveBuf. È possibile determinare la dimensione del blocco ricevuto utilizzando il metodo ReceiveLength. Puoi anche utilizzare un flusso socket (vedi l'articolo TClientSocket). Ed ecco un piccolo esempio (approssimativo):

(Ricevi file tramite socket)

procedura TForm1.ClientSocket1Read(Sender: TObject ;

Socket: TCustomWinSocket);

varl: numero intero;

Buf: PChar ;

Origine: TFileStream;

inizio

(Scriviamo in l la dimensione del blocco ricevuto)

L:= Socket.ReceiveLength ;

(Ordiniamo la memoria per il buffer)

GetMem (buf,l+1 ) ;

(Scriviamo il blocco ricevuto nel buffer)

Socket.ReceiveBuf(buf,l) ;

(Apri un file temporaneo per la scrittura)

Src:= TFileStream.Create("myfile.tmp" ,fmOpenReadWrite) ;

(Inserisci la posizione alla fine del file)

Src.Seek(0,soFromEnd) ;

(Scrivi buffer su file)

Src.WriteBuffer(buf,l) ;

(Chiudi il file)

Src.Free ;

(Liberando la memoria)

FreeMem (buf) ;

FINE ;

Come monitorare una presa
La questione è complessa e richiede una lunga riflessione. Per ora, noterò solo che puoi sempre monitorare il socket creato dal tuo programma :-). I socket (come la maggior parte degli oggetti in Windows) hanno il proprio handle (handle), scritto nella proprietà Handle. Quindi, avendo appreso questo descrittore, puoi controllare liberamente qualsiasi socket (anche quelli creati dal programma di qualcun altro)! Tuttavia, molto probabilmente dovrai utilizzare le funzioni WinAPI Sockets per monitorare il socket di qualcun altro.
Epilogo
Questo articolo mostra i trucchi di base per lavorare con il componente TServerSocket in Delphi e alcuni trucchi generali per comunicare sui socket. Se hai domande, inviamele via e-mail: [e-mail protetta], e ancora meglio - scrivi nel forum di questo sito (Delphi. Domande generali), in modo che altri utenti possano vedere la tua domanda e provare a rispondere!
Karich Nikolaj (Nitro). Regione di Mosca, Zhukovsky

Ho aggiunto il supporto di rete. Viene creato il server separato e il client separato. Il punto è che il server delle applicazioni è in esecuzione, l'utente avvia il client e inserisce la richiesta nell'utente: Moscow Tverskaya 6. Quindi il server elabora la richiesta, riceve i risultati della ricerca da Yandex.Maps e invia l'immagine risultante al client , la parte viene visualizzata nel client nella scheda data del componente TMap che corrisponde alla richiesta dell'utente. Di conseguenza, l'utente può ridimensionarlo, salvarlo e così via.

Pertanto, in questo articolo voglio dirti come ho implementato il client e il server. L'ho fatto con l'aiuto di TClientSocket e TServerSocket, in questo articolo considereremo in dettaglio i metodi che ho utilizzato nel mio progetto.

Innanzitutto, vediamo come questi componenti possono essere installati nell'IDE. Se stai utilizzando l'IDE Delphi 7, per impostazione predefinita questi componenti sono presenti, ma, sfortunatamente, non sono installati, ma questo non è un problema. Dobbiamo solo aprire Delphi e installarlo.

Per fare ciò, esegui il comando Component-Install Packages… e nella finestra che appare, fai clic sul pulsante Aggiungi. Successivamente, è necessario specificare il percorso del file dclsockets70.bpl, che di solito si trova nella cartella BIN per impostazione predefinita. Successivamente, è necessario fare clic sul pulsante OK. Tutto, i tuoi componenti dovrebbero apparire nella scheda Internet (TClientSocket e TServerSocket).

Nel progetto, ho iniziato tutto il lavoro, con uno sviluppo minimo del server. Innanzitutto, ho installato il componente TServerSocket sul modulo. E facendo clic sul pulsante Avvia server, imposta impostazioni iniziali, per inizializzarlo:

server. Porta := Impostazione FormServer. SpinEditPort. valore; //specifica la porta del server server. Attivo := Vero ; //attivalo Server. aprire; ifServer. Attivo quindi iniziare //visualizza un messaggio che il server è attivo e in esecuzione FINE ; …….. //visualizza un errore se il server non è stato avviato

Per inizializzare il server sulla mia macchina, ho solo impostato una porta libera (che non è occupata da altre applicazioni) e l'ho attivata.

In linea di principio tutto qui, per lavoro mi bastava che il server fosse in esecuzione e potevo evadere le richieste dei client che loro inviano.

Per poter ottenere un elenco di client che si connettono al server e lavorare ulteriormente con loro, ho installato il componente TCheckListBox sul modulo e sull'evento OnclientConnect del componente TServerSocket, ho scritto il seguente codice:

procedura TFormServer. ServerClientConnect (Mittente: TObject ; Socket: TCustomWinSocket) ; inizio //monitora la connessione del client richeditlog. SelAttributi . Colore :=clVerde; richeditlog. SelAttributi . Stile := [fsBold] ; CheckListClient. Elementi . Add(Socket.RemoteHost); richeditlog. Linee. Aggiungi ("[" + TimeToStr (Time ) + "] Client connesso: " + Socket. RemoteHost ) ; // aggiunge all'elenco il client che si è connesso richeditlog. Esegui(WM_VSCROLL, SB_BOTTOM, 0) ; FINE ;

Cioè, aggiungo all'elenco i nomi di quei client che si connettono al server per ottenere ulteriori informazioni su di loro.

Ad esempio, puoi ottenere informazioni dettagliate sul cliente:

procedura TFormInfoClient. FormShow(Mittente: TObject) ; inizio // stampa le informazioni sul client didascalia:= "Informazioni per il cliente: "+ formserver. CheckListClient. Elementi [FormServer. CheckListClient. VoceIndice] ; nome locale. Didascalia := FormServer. Server. PRESA. Connessioni [FormServer. CheckListClient. Indice articolo] . Host locale ; ospite locale. Didascalia := FormServer. Server. PRESA. Connessioni [FormServer. CheckListClient. Indice articolo] . Indirizzo locale ; localport. Caption := IntToStr (FormServer. Server . Socket . Connections [ FormServer. CheckListClient . ItemIndex ] . LocalPort ) ; remotename. Didascalia := FormServer. Server. PRESA. Connessioni [FormServer. CheckListClient. Indice articolo] . Host remoto ; Host remoto. Didascalia := FormServer. Server. PRESA. Connessioni [FormServer. CheckListClient. Indice articolo] . indirizzo remoto; remoteport. Caption := IntToStr (FormServer. Server . Socket . Connections [ FormServer. CheckListClient . ItemIndex ] . RemotePort ) ; FINE ;

Puoi ottenere i seguenti dati:

  • nome locale
  • Indirizzo locale
  • porto locale
  • nome remoto
  • indirizzo remoto
  • porto remoto

Ottengo informazioni sul client utilizzando questo codice, che ho selezionato nell'elenco del componente TCheckListBox.

Come puoi vedere, non c'è niente di complicato, per inviare un messaggio al client puoi utilizzare il seguente codice:

IN parentesi quadre, indico a quale client invieremo il messaggio (è uguale al client selezionato nel componente TCheckListBox), specifico #message# nel messaggio - il che significa che questo è un normale messaggio dal server, che dovrebbe essere semplicemente visualizzato nella finestra.

Per ricevere un messaggio dal client al server, abbiamo bisogno dell'evento OnClientRead del componente TServerSocket e di una variabile di testo in cui scriveremo la richiesta inviata dal client.

procedura TFormServer. ServerClientRead(Mittente: TObject ; Socket: TCustomWinSocket) ; var interrogazione: stringa ; inizio //ricevo una richiesta dal client per la carta prova query:= Socket. RiceviTesto ; if pos("interrogazione", interrogazione)<>0 quindi iniziare //richiesta da Yandex o Coordinate Google carte secondo la richiesta del cliente FINE ; //se è solo un messaggio dal client, visualizzalo if pos("#messaggio#", interrogazione)<>0 poi inizio fine ; ……

Da questo codice puoi vedere che il client può inviare sia un normale messaggio al server sia una richiesta di una carta, come: Mosca, Tverskaya, 6.

Per fare ciò, devo determinare dove si trova il solito messaggio e dov'è esattamente la richiesta di ricevere la carta, in modo che il server possa elaborarla in futuro. In questo caso, all'inizio, aggiungo i seguenti identificatori ai messaggi del cliente:

  • #Messaggio#
  • #interrogazione#

Se l'identificatore #message# è presente all'inizio del messaggio del client, allora il server lo riconoscerà come un normale messaggio dal client. Se l'identificativo #query# è presente all'inizio del messaggio, significa che il client ha inviato una richiesta per ricevere una carta.

Inoltre, il client può disconnettersi dal server in qualsiasi momento, dobbiamo anche tenerne traccia per rimuoverlo dall'elenco generale dei client connessi al server. Per fare ciò, seleziona il componente TServerSocket e scrivi il seguente codice nell'evento OnClientDisconnect:

procedura TFormServer. ServerClientDisconnect (Mittente: TObject ; Socket: TCustomWinSocket) ; var i: intero ; iniziare a provare //controlla l'arresto del client richeditlog. SelAttributi . Colore :=clRosso; richeditlog. SelAttributi . Stile := [fsBold] ; for i := 0 al server. PRESA. ActiveConnections - 1 inizia se Server. PRESA. Connessioni[i]. Maniglia = server. PRESA. Connessioni[i]. Gestisci quindi inizia RichEditLog. Linee. Aggiungi ("[" + TimeToStr (Time ) + "] Client disconnesso: " + Socket. RemoteHost ); CheckListClient. Elementi . Elimina(i) ; richeditlog. Esegui(WM_VSCROLL, SB_BOTTOM, 0) ; FINE ; FINE ; infine //-//-//-//-//-// fine ; FINE ;

Esaminiamo tutti i client che abbiamo nell'elenco e se non ne troviamo nessuno, lo rimuoviamo dal componente TCheckListBox, il che significa che il client nella sua applicazione ha fatto clic sul pulsante Disconnetti.




Superiore