|
|
 |
 |
 |
Artykuły |
 |
|
Komunikator w Delphi
13:21:33 25.08.2005
@REIKO
Witam po raz pierwszy!
W moim pierwszym artykule chciałbym Ci pokazać, w jaki sposób można napisać prosty komunikator w Delphi.
Utworzymy dwie aplikacje (klient i serwer) No to do dzieła, ale najpierw potrzebne Ci będą (pomijając takie rzeczy jak system operacyjny i Delphi :D )
komponenty Indy, takie jak: IdTCPClient (aplikacja klient), IdThreadMgrDefault oraz IdTCPServer (aplikacja serwerowa) (cały pakiet komponentów indy10 dla Delhi 5-8 można pobrać ze strony http://www.atozed.com/indy/plus/install.iwp ).
Ok, bierzmy się do pracy.
1. Aplikacja serwerowa.
Na formę wstawiamy komponent Memo (zakładka Standard), 2 przyciski button (także zakładka „standard”). Właściwość Caption pierwszego przycisku ustawiamy na „polacz”, a drugiego na „zamknij”. Wstawiamy też komponent Edit (również zakładka „standard”). Oprócz tego z karty Indy Misc wrzucamy na formę komponent IdThreadMgrDefault oraz komponent IdTCPClient z zakładki Indy Servers. Ten pierwszy umożliwia obsługę tzw. Wątków, drugi zaś umożliwia przesyłanie wiadomości od klienta do klienta.
OK, dość teorii. Teraz trochę kodu:
Kliknij 2 razy na przycisk z napisem polacz, otwiera się okno w które trzeba wpisać kod:
IdTCPServer1.DefaultPort:=strtoint(edit1.text); // w edit1 wpisujemy nr portu połączenia (pamiętaj, że numery potrów od 1 do 1300 sa zarezerwowane przez system (poczta, Internet itp.)
idserwer.Active:=true; // gotowość do nawiązania połączenia
Następnie wybieramy komponent IdTCPServer1 i w oknie Object Inspector przechodzimy na zakładkę Events i z listy klikamy na pozycję ThreadMgr i wybieramy pozycję IdThreadMgrDefault1. Klikamy również na zdarzenie OnConnect komponentu IdTCPServer1 i wpisujemy kod:
var
NewConnection: WConnection;
begin
GetMem(NewConnection, SizeOf(TConnection));
NewConnection.Host := AThread.Connection.LocalName;
NewConnection.Thread := AThread;
AThread.Data:=Tobject(NewConnection);
try
ConnectionLst.LockList.Add(NewConnection);
finally
ConnectionLst.UnlockList;
end;
memo1.Lines.Add('Polaczenie: '+NewConnection.Host + '"' + TimeToStr(Time));
OK, teraz napiszemy kod, który zostanie wykonany w momencie przyjścia wiadomości od aplikacji klienckiej. Więc dla zdarzenia OnExecute komponentu IdTCPClient1 wpisujemy kod:
var
DestThread: TIdPeerThread;
i: Integer;
DestConnection: WConnection;
Package, NewPackage: TPackage;
begin
begin
AThread.Connection.ReadBuffer (Package, SizeOf (Package));
komunikaty.Lines.Add (TimeToStr(Time)+ ' - ' + Package.UserNick+ ' : '+Package.Txt);
NewPackage := Package;
with ConnectionLst.LockList do
try
for i := 0 to Count-1 do
begin
DestConnection := Items[i];
DestThread := DestConnection.Thread;
DestThread.Connection.WriteBuffer(NewPackage, SizeOf(NewPackage), True);
end;
finally
ConnectionLst.UnlockList;
end;
end;
Krótkie objaśnienie:
Zmienna DestThread będzie przechowywać wątek docelowy.
Zmienna i przyda się w konstruowaniu procedury interakcyjnej.
Zmienna DestConnection będzie wskazywać kolejnych klientów klientów listy ConnectionLst.
Zmienne Package i NewPackage typu TPackage będą przechowywały dane, które przesłał klient. Typ TPackage zawiera 2 rekordy Txt czyli dane tekstowe wysłane przez klienta oraz rekord Nick, czyli nazwę klienta.
Ostatnie zdarzenie do oprogramowania w aplikacji serwerowej jest zdarzenie OnDisconnect, czyli rozłączenie. A więc dla zdarzenia OnDisconnect komponentu IdTCPServer1 przypisujemy kod:
var
ActiveConnection: WConnection;
begin
ActiveConnection := WConnection(AThread.Data);
try
ConnectionLst.LockList.Remove(ActiveConnection);
finally
ConnectionLst.UnlockList;
end;
FreeMem(ActiveConnection);
AThread.Data := nil;
W tej instrukcji usuwamy dane połączenie z listy ConnectionLst i zwalniamy pamięć.
Ostatnim krokiem jest zdefiniowanie struktur danych (typ WConnection i TPackage). Więc na początku kodu naszej aplikacji serwerowej, po deklaracji uses i tuż po słowie type wpisujemy kod:
WConnection = ^TConnection;
TConnection = record
Host : String[20];
Thread : Pointer;
end;
TPackage = record
UserNick,
Txt : string[255];
end;
Możemy teraz skompilować projekt aplikacji serwerowej i uruchomić go, ale nie będzie z niego pożytku bez aplikacji klienckiej, którą zaraz też napiszemy. :D
2. Aplikacja klientka.
Na formę wrzucamy komponenty: 2 razy memo (odbieranie i wysyłanie wiadomości), trzy komponenty edit (Adres IP komputera, na którym uruchomiona jest aplikacja serwerowa; Nick oraz numer potru, na którym nasłuchuje aplikacja serwerowi), i przycisk button (połączenie z aplikacją serwerową). Teraz komponent memo1 nadajemy nazwę (pole name w object inspektor) „wiadomości”, a memo2 nadajemy nazwę „dowyslania”. Przyciskowi dajemy nazwę „polacz”. Pole edit odpowiedzialne za adres IP serwera nadajemy nazwę „IP”, polu odpowiedzialnemu za Nick klienta nadajemy nazwę „nick” i pole odpowiedzialne za port, na którym nasłuchuje serwer nazywamy „port”. OK., to na razie tyle. Teraz bierzemy się za kod. Zaczniemy od przycisku „polacz”. Dla zdarzenia OnClick przycisku polacz wpisujemy kod:
try
IdTCPClient1.Host := ip.Text;
IdTCPClient1.Port:= StrToInt(port.Text);
IdTCPClient1.Connect(10000);
ClientRecive := TClientOnReceive.Create(True);
ClientRecive.FreeOnTerminate:=True;
ClientRecive.Resume;
except
on E: Exception do MessageDlg ('polaczenie niemozliwe: '+#13+E.Message, mtError, [mbOk], 0);
end;
Opis: w tym kodzie jest napisane, jaki adres IP ma aplikacja serwerowa; następnie jest pokazane, jaki numer ma port połączenia pomiędzy klientem a serwerem no i później polecenie otwiera połączenie z serwerem.
Teraz wybieramy komponent, który nazwaliśmy „dowyslania” i w object inspector’rze przechodzimy na zakładkę „events” i dla zdarzenia OnKeyPress wpisujemy kod:
var
SendPackage:TPackage;
begin
if (key = #13) then
begin
wyslij.BevelOuter:=bvRaised;
SendPackage.UserNick := nick.Text;
SendPackage.Txt := dowyslania.Text;
IdTCPClient1.WriteBuffer (SendPackage, SizeOf (SendPackage), true);
dowyslania.text:='';
end;
Opis: Tworzymy zmienną typu TPackage (pozwala określić typ danych); następnie do stworzonej zmiennej wpisujemy zawartość pól z naszym pseudonim i wiadomością do wysłania. Ostatnia instrukcja ma za zadanie wysłanie naszej „paczki” do aplikacji serwerowej. Wymaga ona 3 parametrów: pierwszy określa zmienną zawierającą wysyłane dane, drugi informuje i ich objętości. Ostatni parametr okteśka sposób wysłania wiadomości (jeśli jest ustawiony na „true”, wiadomość jest wysłana natychmiastowo).
Teraz przystąpimy do napisania funkcji, która będzie obsługiwać zdarzenie przesyłu danych do klienta - ClientReceive. A to co jest pod spodem wpisujemy tuż po słowie type znajdującym się na początku kodu naszego programu:
TClientOnReceive = class(TThread)
private
ActiveP: TPackage;
procedure Action;
protected
procedure Execute;
override;
end;
Utworzymy jeszcze procedurę Execute, której kod jest pod spodem, i który wpisujemy tuż po słowie implementation:
procedure TClientOnReceive.Execute;
begin
while not Terminated do
begin
if not glowna.IdTCPClient1.Connected then
Terminate
else
try
glowna.IdTCPClient1.ReadBuffer(ActiveP, SizeOf (ActiveP));
Synchronize(Action);
except
end;
end;
end;
Procedura ta aż do chwili zamknięcia wątku sprawdza, czy klient jest połączony z serwerem. Jeśli nastąpi połączenie podejmowana jest próba pobierania danych przez serwer. Dane zostaną zapisane w zmiennej ActiveP i zostanie wywołane polecenie, które spowoduje przesłanie uaktualnionych zmiennych do procedury Action, którą zaraz napiszemy i będzie to ostatnia rzecz, jaką dziś napiszemy (jeśli chodzi o komunikator :D ).
Procedurę Action, podobnie jak Execute, również umieszczamy po słowie implementation. Kod procedury action:
procedure TClientOnReceive.Action;
begin
glowna.wiadomosci.Lines.Add ('[' + ActiveP.UserNick + ']: ' + ActiveP.Txt);
end;
Jej jedynym zadaniem jest wyświetlenie danych za pomocą komponentu memo noszącego nazwę „wiadomości”.
I to tyle. Teraz można skompilować aplikację kliencką i sprawdzić jej działanie. Proponuję dodanie kilku funkcji. Należy pamiętać, że aby komunikator działał należy w aplikacji serwerowej i klienckiej wpisać ten sam numer portu, w aplikacji klienckiej należy wpisać w polę adresu IP adres IP komputera, na którym nasłuchuje aplikacja serwerowa.
Instrukcja obsługi:
Uruchamiamy aplikację serwerową i wpisujemy port, na którym zostanie nawiązane połączenie.
Klikamy na „Połącz”
Aplikacja serwerowi już jest gotowa do połączenia z aplikacją kliencką.
Uruchamiamy aplikację kliencką i wpisujemy w wyznaczone pola nr portu (ten sam, który jest wpisany w aplikacji serwerowej), nick i adres IP komputera, na którym uruchomiona jest aplikacja serwerowa.
Klikamy na przycisk „Połącz”. Już jesteśmy połączeni z serwerem. Teraz 2 osoba musi zrobić to samo z aplikacją kliencką klientką tą różnicą, że wpisze inny nick. Teraz każdy klient może wpisywać swoją wiadomość w pole memo (dowyslania) i Enterem wysyłamy wiadomość. Wiadomości przychodzące można odczytywać na komponencie memo (wiadomości). To samo robi osoba 3, 4, 5……. Itd.
To chyba wszystko.
PS. Serdeczne podziękowania dla redakcji „Komputer Świat Ekspert”.
Komentarzy: 4 | Głosuj (1,
2,
3,
4,
5,
6) | Ocena: 3.47 | Czytane: 9619 |  |
 |
Komentarze |
 |
|
Musisz się zalogować aby mieć możliwość komentowania
16:06:04 13.09.2006 @Kamsys
EE, to mi nie działa. Jeśli chodzi o aplikacje serwerowa to wyswietla blad: undeclarated identifier: ConnectionLst, kupa
14:47:00 28.08.2007 @artura4
Fakt, bardzo niedbale napisane. Najpierw zastosowane nieznane Typy danych a potem dopiero ich deklaracje, nie da się tego etapami wpisywać i kompilować bez błędów. Proponuje zobaczyć jak napisany jest artykuł "Sockety" wzór do naśladowania. Szkoda bo teraz nie bardzo wiem jaka jest różnica międy ClientSocket i ServerSocket a zastosowanymi tu IdTCPClient i IdTCPServer z palety INDY. Pewnie INDY mają większe mozliwości, ale mi nie działają.
22:38:11 18.12.2007 @REIKO
1. Ale gdzie masz blad? W jakiej linii? Napisz mi wszystko na reiko7@wp.pl, Kamsys
2. artura4 dlaczego uwazasz tamten art jako wzor do nasladowania skoro go nie rozumiesz? Najpierw zapoznaj sie z pojeciami co to jest serwer a co to jest klient, co to jest protokol TCP/IP oraz UDP ;) To podstawy podstaw...
22:41:55 18.12.2007 @REIKO
1. Ale gdzie masz blad? W jakiej linii? Napisz mi wszystko na reiko7@wp.pl, Kamsys
2. artura4 dlaczego uwazasz tamten art jako wzor do nasladowania skoro go nie rozumiesz? Najpierw zapoznaj sie z pojeciami co to jest serwer a co to jest klient, co to jest protokol TCP/IP oraz UDP ;) To podstawy podstaw...
|  |
|
 |
|