Létrehozása többfelhasználós csevegés Borland Delphi

Egy korábbi cikkben ( „Creating a kliens-szerver”) írta le a fejlődés egy egyszerű beszélgetés két felhasználó. A szerkezet a chat „head-to-head” nagyon egyszerű, mert csak egy csatorna, egyrészt, hogy a szerver, a másik - az ügyfél. Multi-felhasználó-szerkezete némileg bonyolultabb. Van egy szerver és több ügyfél. A szerver egyidejűleg elvégzi a feldolgozást a bejövő üzenetek, elküldi őket a kívánt csatornát, felismeri és megjeleníti az összes felhasználó, sok felhasználó közli az adott pillanatban. Ebben a cikkben megpróbáljuk megvalósítani mindezt.

Multiplayer csevegés (Multi-user on-line)

Kezdjük az IM alkalmazás fejlesztés kész formák a korábbi cikkben, illetve az új. Ez az, ami kell a következő formában:

Komponenseket Delphi ServerSocket és ClientSocket standard csomag nem mindig jelenik meg az Internet palettán. és meg kell töltse le a következő:

válassza ki a menü: Component - Csomagok telepítése ... - Add. Ezután meg kell adni a fájl ... \ bin \ dclsockets70.bpl.

Ha új elemek:

Mi most úgy a szerver elv. Hagyományosan a ServerSocket hogy elfogadja kliens csomagokat a OnClientRead. de ez a módszer nem túl kényelmes, mert a csomag azonosító (aki küldött) kell bütykölni a szerkezet „fogadó \ válasz”, és úgy dönt, hogy a szinkronizálás fog bekövetkezni. Sokkal könnyebb és hatékonyabb használatát ciklus a felhasználók száma, ami által lefolytatott „monitoring” minden csatornát és csomag feldolgozás, ha jött egy adott csatornára van rendelve egy adott felhasználót. Az eljárás a „hallgató” csatornákon végzi a szervezetben időzítő intervallum (Interval) munka, ami lehet, hogy meg kell változtatni (chat általában 500 ms, a játék kell lényegesen kevesebb). Itt általános szerkezetét a felmérési eljárást:

eljárás TForm1.Timer1Timer (Sender: TObject);
kezdődik
// feltétele telepített csatornák
ha ServerSocket.Socket.ActiveConnections<>0, akkor
kezdődik
// hurok meglévő csatornákon keresztül
i: = 1 ServerSocket.Socket.ActiveConnections do
kezdődik
// mentse a csomagot (ha semmi sem küldött egy üres csomag)
szöveg: = ServerSocket.Socket.Connections [i-1] .ReceiveText ();
// azt jelzi, hogy a csomag nem üres
ha szöveges<>„” Aztán
kezdődik

// határozza parancsok
esetében com
kód: kezdődik

végén;
kód: kezdődik

végén;
...........................................
végén;
végén;
végén;
végén;
// engedélye a frissítési eljárások
ha UpdDo = igaz, akkor
kezdődik

// zár engedélyével
UpdDo: = false;
végén;
végén;

Ha észreveszi, hogy a ciklus kezdődik az egységet és inicializálás csatorna furcsa kifejezés [i-1] (ahelyett, logikus, hogy nullával kezdődik és inicializálás), akkor ez a megoldás jelentősen megkönnyíti a szervezet számos eljárást. Például a felhasználói listán, akkor a kiszolgáló szám alatt bejegyzett „0”, és az ügyfelek - kezdve az „1”. Ugyancsak célszerű kombinálni a csatornák száma (ServerSocket.Socket.ActiveConnections) eljárások meghatározására felhasználói aktivitás.
Az utolsó feltétel a szervezetben időzítő szükséges, hogy késleltesse a végrehajtásának egyes frissítési eljárásokkal. Ezeket az eljárásokat kell végezni a végén „hallgat” nyitott csatornák, és nem mindig (ha egy csapat).
Ez az algoritmus alkalmazható szinte bármilyen kliens-szerver, beleértve a játékokat.

FIGYELEM! Ha nem vagyunk biztosak a helyességét a kódot írsz utasítások feldolgozását a hurok, „hallgat” nyitott csatornák, a funkció mindig alkalmazzák Try..Except..End;. amelynek révén elkerülhető a súlyos hibák, mert a ciklus ismételhetőség nagyon gyors lehet. például:

megpróbál

kivéve
// Az időmérő leállításához és a kapcsolódó intézkedéseket
Vége;

Egyenesen a chat alkalmazás és annak eljárásait. Mint korábban, a pontosságának ellenőrzését a bemeneti értékek terén nem lesz.
Hozzon létre egy új típusú használatáért tömb tárgyak, így sokkal kényelmesebb:

Típus
TUserList = objektum
Állapot: Byte; // 1 - Szerver 2 - ügyfél
Rec: Boolean; // jelölje meg az összes blog bejegyzést a listában
Név: String; // név (nick)
Kép: Byte; // index ikonok
végén;

Itt vannak a változók, amelyek szükségesek lesznek a programban:

var
Form1: TForm1;
i, j, com, ContList: Byte;
len, pos, x: a Word;
szöveg, StrUserList: String;
UpdDo: Boolean;
Buf: array [0..3] bájt;
UserMas: array [0..255] a TUserList; // tömb tárgyak
UItems: TListItem;

Nézzük ismertesse az eljárást OnCreate formája:

Az eljárás a „hallgat” nyitott csatornák a szerver így néz ki:

Fordítás szoftver szerver módban a gomb megnyomásával a „Create server” (ServerBtn). Itt az az eljárás, egy gomb megnyomásával ServerBtn (onclick):

eljárás TForm1.ServerBtnClick (Sender: TObject);
kezdődik
ha ServerBtn.Tag = 0, akkor
kezdődik
// a kulcs ClientBtn és helyszíni HostEdit, PortEdit, NikEdit blokkolja a
ClientBtn.Enabled: = false;
HostEdit.Enabled: = false;
PortEdit.Enabled: = False;
NikEdit.Enabled: = false;
// levelet a megadott portot a ServerSocket
ServerSocket.Port: = StrToInt (PortEdit.Text);
// elindítani a szerver
ServerSocket.Active:=True;
// hozzá ChatMemo üzenetet az idő a teremtés
ChatMemo.Lines.Add ( '[' + TimeToStr (Time) + '] Szerver létre.');
// változtatni a címke
ServerBtn.Tag: = 1;
// helyett a gomb felirata
ServerBtn.Caption: = 'Zárja le a szerver';
// kiszolgáló bekapcsolására időzítő
ServerTimer.Enabled: = true;
// belépünk szerver beállításokat
UserMas [0] .Status: = 1;
UserMas [0] .Rec: = True;
UserMas [0] .name: = NikEdit.Text;
UserMas [0] .Image: = 1;
// lehetővé frissítés
UpdDo: = true;
vég
más
kezdődik
// kikapcsolja a szerver időzítő
ServerTimer.Enabled: = false;
// törli a szerver beállításait
UserMas [0] .Status: = 0;
UserMas [0] .Rec: = False;
UserMas [0] .name: = 'ismeretlen';
UserMas [0] .Image: = 0;
// lehetővé frissítés
UpdDo: = true;
// törölje a listát az ügyfelek
UserListView.Items.Clear;
// a kulcs ClientBtn és helyszíni HostEdit, PortEdit, NikEdit unlock
ClientBtn.Enabled: = true;
HostEdit.Enabled: = true;
PortEdit.Enabled: = true;
NikEdit.Enabled: = true;
// közel szerver
ServerSocket.Active:=False;
// képernyőüzenettel ChatMemo
ChatMemo.Lines.Add ( '[' + TimeToStr (Time) + '] kiszolgáló zárt.');
// visszatér az eredeti értékének a címke
ServerBtn.Tag: = 0;
// visszaadja az eredeti kulcsot felirattal
ServerBtn.Caption: = 'Create Server';
végén;
végén;

További olyan események, amelyek meg kell történnie egy bizonyos állapotban ServerSocket „a. Írjon egy eljárást, ha egy kliens csatlakozik a szerverhez (OnClientConnect):

eljárás TForm1.ServerSocketClientConnect (Sender: TObject;
Hüvely: TCustomWinSocket);
kezdődik
// hozzá egy üzenetet az idő ChatMemo ügyfél kapcsolat
ChatMemo.Lines.Add ( '[' + TimeToStr (Time) + '] csatlakoztassa a kliens.');
// lehetővé frissítés
UpdDo: = true;
végén;

Írjon egy eljárást, amikor a kliens bontja (OnClientDisconnect):

eljárás TForm1.ServerSocketClientDisconnect (Sender: TObject;
Hüvely: TCustomWinSocket);
kezdődik
// hozzá egy üzenetet az idő ChatMemo kliens bontja
ChatMemo.Lines.Add ( '[' + TimeToStr (Time) + '] Kliens csatlakoztatva.');
// lehetővé frissítés
UpdDo: = true;
végén;

Üzenetek küldésére. Megvan végzett nyomja meg a „Küldés” (SendBtn), de szükséges, hogy ellenőrizze a program módban a szerver vagy kliens. Írunk le eljárását (onclick):

eljárás TForm1.SendBtnClick (Sender: TObject);
kezdődik
// ellenőrizze, hogy melyik módban a program
ha ServerSocket.Active = igaz, akkor
// az üzenetet küldeni a szerver minden felhasználó számára
i: = 0 ServerSocket.Socket.ActiveConnections-1 do
ServerSocket.Socket.Connections .SendText ( '0 [' + TimeToStr (Time) + ']' + NikEdit.Text + ':' + TextEdit.Text)
más
// üzenet küldése az ügyfél
ClientSocket.Socket.SendText ( '0 [' + TimeToStr (Time) + ']' + NikEdit.Text + ':' + TextEdit.Text);
// megjeleníti az üzenetet ChatMemo
ChatMemo.Lines.Add ( '[' + TimeToStr (Time) + ']' + NikEdit.Text + ':' + TextEdit.Text);
// törölje a TextEdit
TextEdit.Clear;
végén;

Client Mode. Ha megnyomja a „Connect” gomb (ClientBtn), blokkolt ServerBtn és aktivált ClientSocket. Itt az eljárás ClientBtn (onclick):

Eljárások OnConnect. OnDisconnect. OnRead ügyfél ClientSocket. Először olvassa el az üzeneteket a szerver (OnRead):

Ezután minden egyszerű, a szokásos adagolása ChatMemo adott üzenet:

eljárás TForm1.ClientSocketConnect (Sender: TObject;
Hüvely: TCustomWinSocket);
kezdődik
// hozzá ChatMemo üzenet szerver kapcsolat
ChatMemo.Lines.Add ( '[' + TimeToStr (Time) + „] kapcsolódni a szerverhez.„);
végén;

eljárás TForm1.ClientSocketDisconnect (Sender: TObject;
Hüvely: TCustomWinSocket);
kezdődik
// hozzá ChatMemo a kommunikáció elvesztése üzenet
ChatMemo.Lines.Add ( '[' + TimeToStr (Time) + '] kiszolgáló nem található.');
végén;

Információs tárház felhasználóink ​​tömb aktusok eljárás befejezését és a frissítés a következő:

eljárás TForm1.UpdateUserMas;
kezdődik
// törölje a sor információt
i: = 1 és 255 do
kezdődik
UserMas .Status: = 0;
UserMas .Rec: = false;
UserMas .name: = 'ismeretlen';
UserMas .Image: = 0;
végén;
// töltse ki a felhasználói adatok
ha ServerSocket.Socket.ActiveConnections<>0, akkor
kezdődik
i: = 1 ServerSocket.Socket.ActiveConnections do
kezdődik
UserMas .Status: = 2;
UserMas .name: = 'ismeretlen';
UserMas .Image: = 0;
// kérje a nevet (becenevet) felhasználó saját csatornát (parancs kódja - 1)
ServerSocket.Socket.Connections [i-1] .SendText ( '1');
végén;
végén;
végén;

UserListView lista frissül a következő eljárás szerint:

eljárás TForm1.UpdateUserList;
kezdődik
// törölje a listát az ügyfelek
UserListView.Items.Clear;
// törölje a változó
StrUserList: = '';
// nullára ki a rögzítési jel
ContList: = 0;
// végigmenni egy sor csatornák
i: = 0-tól 255 do
kezdődik
// ha a rekord nem üres
ha UserMas .Status<>0, akkor
kezdődik
// hozzá egy sort UserListView
UItems: = UserListView.Items.Add;
UItems.Caption: = UserMas .name;
UItems.ImageIndex: = UserMas .Image;
// ha a felhasználó nem kerül rögzítésre
ha UserMas .Rec = False majd ContList: = 1;
// összeállításához felhasználó húr
StrUserList: = StrUserList + UserMas .name + Chr (152);
végén;
végén;
// ha minden felhasználó észleltek, és van legalább egy csatornát
ha (ContList = 0) és (ServerSocket.Socket.ActiveConnections<>0), akkor
kezdődik
// fut végig a nyitott csatornákon
i: = 0 ServerSocket.Socket.ActiveConnections-1 do
kezdődik
// elküldi a felhasználó egy listát string (parancs kódja - 2)
ServerSocket.Socket.Connections .SendText ( '2' + StrUserList);
végén;
végén;
végén;

Ez minden. Ne félj kísérletezni, de ne feledje, az alapvető szabályokat a biztonságos programozás. Sok szerencsét!

Kapcsolódó cikkek