Questa lettera è stato originariamente pubblicato a delphi3000.com

La documentazione relativa al Delphi TServerSocket della capacità multithreading può apparire un po 'sparsi per l'occhio non addestrato. Vorrei cercare di gettare un po 'più di luce su questo argomento.

In realtà è piuttosto facile fare una multithread server in ascolto per i messaggi su un socket. Delphi è un componente per questo: la TServerSocket.

Ma avete bisogno di un po 'di conoscenza di usarlo.

Al fine di strutturare il vostro lavoro, dovete:

- Aggiungere un TServerSocket al tuo modulo principale.
- Impostare la proprietà di ServerType stThreadBlocking
- Creare una nuova unità (vedi sotto), contenente il server thread.


Effettua il seguente codice sul OnSocketGetThread

procedura TfrmMain.fSocketGetThread (Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
iniziare
/ / In questo modo si crea l'oggetto TServerThread ho mostrato
/ / Il codice qui di seguito. Un nuovo oggetto viene creato ogni volta che
/ / Un nuovo collegamento è stabilito.
SocketThread: = TServerThread.Create (FALSE, ClientSocket);
fine;

Il TServerThread è un oggetto che ho creato io. L'oggetto inheits da TServerClientThread e contiene il codice che in realtà sono la lettura e la scrittura da presa.

L'unità che ho creato contiene almeno il seguente codice:

serverthread unità;

interfaccia

usa
finestre, scktcomp, SysUtils, le classi, le forme;

tipo + + digitare
EServerThread = classe (Eccezione);
/ / La serverthread è un discendente del
/ / TServerClientThread
TServerThread = classe (TServerClientThread)
privato
fSocketStream: TWinSocketStream;
pubblico
procedura ClientExecute; ignorare;
/ / La ClientExecute ignorare il
/ / TServerClientThread.ClientExecute
/ / E contiene il codice vero e che è
/ / Eseguito quando il thread è cominciato
fine;

attuazione

TServerThread.ClientExecute procedura;
iniziare
ereditato FreeOnTerminate: = TRUE;
provare
fSocketStream: = TWinSocketStream.Create (ClientSocket,
100000);
/ / 100000 è il timeout in miliseconds.
provare
mentre (non scaduto) e (ClientSocket.Connected) do
provare
/ / Questo è dove si farà il reale
/ / In attesa di input, di lettura e scrittura
/ / Gli esempi qui di seguito mostra ciò che si può
/ / Mettete qui.
eccetto e: fare eccezione
iniziare
/ / Si è verificato un errore, chiudere e uscire
ClientSocket.Close;
Termina;
fine;
fine;
finalmente
fSocketStream.Free;
fine;
eccetto e: fare eccezione
iniziare
/ / Si è verificato un errore, chiudere e uscire
ClientSocket.Close;
Termina;
fine;
fine;
fine;

Quando la connessione è stabilita, il thread deve aspettare che i dati in entrata. È possibile utilizzare questo codice di aspettare i dati:

se (non scaduto) e
(Non fSocketStream.WaitForData (1000000)) allora
iniziare
/ / Maneggiare il timeout
fine;
/ / Non ci sono i dati in arrivo sul socket!

Per leggere i dati, si dovrebbe avere un buffer per memorizzare i dati pollici Normalmente il buffer è un PByteArray o di un array di caratteri. In questo esempio ho un buffer chiamato fRequest che è un array di caratteri. Inoltre mi aspetto un numero fisso di byte. La mia matrice è la dimensione della costante REQUESTSIZE.

var
ac, readlen: integer;
iniziare
FillChar (fRequest, REQUESTSIZE, 0);
ac: = 0;
ripetere
readlen: = fSocketStream.Read (fRequest [AC],
1024);
/ / Ho letto in blocchi di 1024 byte fino a quando il tampone
/ / È piena
ac: = ac + readlen;
fino al (readlen = 0) o (ac = REQUESTSIZE);
fine;

Se readlen è 0, allora io non ricevere più dati. La funzione Leggi volte dopo 100000 miliseconds a quanto dichiarato nella TWinSocketStream.Create (). Se non si conosce la quantità di dati di aspettarsi, si dovrebbe impostare questo timeout abbastanza piccoli. 30 secondi al massimo dovrebbe essere nella maggior parte delle situazioni.

Quando si invia una risposta, si dovrebbe essere a conoscenza dei vostri clienti comportamento. Molti clienti aspetta solo di un pacchetto di replica, si aspetta che molti altri pacchetti.
In questo esempio, ho un cliente che si aspetta solo un unico pacchetto, in modo che ho per inviare i miei dati in un unico pezzo:

fSocketStream.WriteBuffer (fRep, fReplySize);

Il fRep è la risposta del buffer, e fReplySize è la dimensione del replybuffer.

Average rating: