Mam oto taki kod serwera:
program Serwer;
{$mode objfpc}{$H+}
{------------------------------------------------------------------------------}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes,blcksock,synsock,sysutils,Crt
{ you can add units after this };
{------------------------------------------------------------------------------}
{$R *.res}
Type
TClient = class(TThread)
private
ClientSock : TTCPBlockSocket;
protected
procedure Execute; override;
end;
{------------------------------------------------------------------------------}
Var
Server : TTCPBlockSocket;
Client : Array of TClient;
Socket : TSocket;
ConnectedClients : LongInt;
FreeClients : LongInt;
CanRead : Boolean;
Key : Char;
i : LongInt;
{------------------------------------------------------------------------------}
Procedure TClient.Execute;
Var
buff : String;
Begin
FreeOnTerminate := True;
ClientSock := TTCPBlockSocket.Create;
ClientSock.Socket := Socket;
Repeat
buff := ClientSock.RecvString (1);
If buff = 'connected' Then
Writeln ('Podłączono ',ConnectedClients,' klientów')
else If buff <> '' Then
Writeln (buff);
Until (buff = 'end') or (buff = 'END');
ClientSock.CloseSocket;
ConnectedClients := ConnectedClients - 1;
end;
{------------------------------------------------------------------------------}
Begin
ClrScr;
// Start serwera
Write ('Inicjacja serwera...');
Server := TTCPBlockSocket.Create;
Server.Bind('127.0.0.1', '1234');
If Server.LastError <> 0 Then
Begin
Write ('Błąd: ');
Writeln (Server.LastErrorDesc);
ReadKey;
Halt (Server.LastError);
end;
ConnectedClients := 0;
FreeClients := 0;
Server.Listen;
Writeln ('Zakończona');
// Praca serwera
Repeat
CanRead := Server.CanRead (1);
If CanRead Then
Begin
Socket := Server.Accept;
ConnectedClients := ConnectedClients + 1;
FreeClients := FreeClients + 1;
SetLength (Client,FreeClients);
Client[FreeClients-1] := TClient.Create (false);
end;
If KeyPressed Then Key := ReadKey;
Until (Key = 'q') or (Key = 'Q');
// Koniec pracy i zatrzymanie serwera
For i := 0 To FreeClients-1 Do Client[i].Free;
Server.CloseSocket;
end.
Napisałem takie coś bo uczę się jak zastosować wielowątkowość razem z komunikacją programów przez sieć. I z tego co zauważyłem to program owszem łączy się z wieloma klientami wyświetla przesłane do niego stringi oraz ilość podłączonych klientów ale gdy naciskam q aby go zakończyć to zawiesza się na pętli
For i := 0 To FreeClients-1 Do Client[i].Free;
Jeśli tą pętlę wywalę z programu to program zamyka się poprawnie a ponieważ jest to koniec programu to wątki poboczne też się zamykają więc w sumie nie jest ta pętla potrzebna ale mimo wszystko chciałbym wiedzieć czemu ona nie działa. Ponieważ będzie mi to potrzebne na zamykanie wątków klientów którzy się już odłączyli.
To raz a dwa w głównym wątku po podłączeniu klienta zmieniam wartość ConnectedClients o 1 w górę i ta wartość się zmienia.
W wątku pobocznym gdy on się kończy zmieniam tę wartość o 1 w dół i tutaj ta wartość już zmienić się nie chce. Wygląda na to że w wątkach pobocznych nie można zmieniać zmiennych globalnych bo nie nalezą one do wątku pobocznego tylko głównego i tu moje drugie pytanie. Jak modyfikować zmienne globalne z wątku pobocznego?
PS.
Jest to mój pierwszy program z wykorzystaniem wielowątkowości i dobrze wiem, że nie jest idealny, więc proszę nie wieszajcie na mnie psów. Każdy kiedyś zaczynał :)