Главная Новые темы Список тем Задать вопрос Поиск  

Форум "Delphi"


Паскаль, Делфи


 #0  marishkin66 © 15.12.04 11:52:14 - 04.09.07 12:28:54

пишу чат (IdTCPClient/IdTCPServer)



Пытаюсь написать простейший чат с использованием компонентов INDY (IdTCPClient, IdTCPServer). Возникло несколько вопросов... Как организовать без использования таймера "прослушку" сервера? (т.е. если от клиента пришло сообщение его сразу должен получить и другой клиент) Как рассылать сообщение определенному клиенту? Помогите, пожалуйста! Может у кого есть примеры? Цитата

 #1 Паша © 15.12.04 12:05:02

с этими компонентами не работал, так что подробно не скажу. клиент, когда цепляется к серверу, авторизируется, т.е. имя машины(IP), имя пользователя, пароль. т.е. сервак знает, кто к нему подключен. потом, если сообщение идет определенному пользователю, сервер ищет его в списке подключенных и пересылает сообщение. если общее сообщение - по всем подключившимся. в принципе, в сети полно примеров такой лабуды на сокетах. поищи что-то наподобие "чат на основе сокетов"
 #2  marishkin66 © 15.12.04 12:13:37

да, чат на основе сокетов довольно простая штука!
я пока написала, только вот что
Сервер:
procedure TfmServer.IdTCPServer1Execute(AThread: TIdPeerThread);
var
s: String;
begin
 with AThread.Connection do
 try
  s := ReadLn;
   WriteLn(s);
 finally
 Disconnect;
 end;
end;
Клиент:
procedure TfmClient.BBtnSendClick(Sender: TObject);
begin
 with IdTCPClient1 do
 begin
 try
  Connect;
  try
     WriteLn(edClientText.Text);
     mmAllMsg.Lines.Add(ReadLn);
 finally
 Disconnect;
 except
   ShowMessage('Communication Exception: /////');
 end;
 end;
end;

В принципе, можно при создании клиентской формы отправлять какое-нить (помеченое) сообщение серверу и так вести учет клиентам.
 #3  marishkin66 © 15.12.04 12:15:27

Но так, сообщение получает только тот, кто его и отправил. Клиент соединяется делает что-то и отсоединяется. Наверное, надо, чтобы он все время был подключен к серверу?
 #4  marishkin66 © 15.12.04 12:19:35

помогите, пли-и-исс...
 #5 Паша © 15.12.04 12:26:57

да, он должен быть все время подключенным. если надо, и мыло живое, могу выслать пару статеек по чату на сокетах с примерами.
 #6  marishkin66 © 15.12.04 12:33:08

Да, конечно! marishkin66(собачка)mail.ru пасиба
 #7  marishkin66 © 15.12.04 12:40:48

вот, нашла кое-что
Но так и не поняла где определен тип PClient...
 #8 Deep © 15.12.04 12:43:12

> Клиент соединяется делает что-то и отсоединяется. Наверное,
> надо, чтобы он все время был подключен к серверу?

совсем не объязательно. Если получателя на даный момент в сети нет, тогда сообщение сохраняется на сервере и будет отправлено получателю, когда тот войдет в сеть(т.е. зарегистрируется на сервере). Имено так поступает сервер ICQ.
 #9  marishkin66 © 15.12.04 12:46:14

"сообщение сохраняется на сервере" В буфер класть?
проблема в отсылке сообщений всем кто есть в сети. =(( просто не знаю как это сделать...
 #10 Deep © 15.12.04 13:11:28

> В буфер класть?
лучше в файл писать. Потому как если сервер вырубиться -- неотправленные сообщения из буфера пропадут.


> проблема в отсылке сообщений всем кто есть в сети.
погоди, погоди. Ты хочешь сделать чат для локальной сети или для интернета? Послать всем пользователям интернета -- это знаешь ли, накладно.   А вод для всех зарегистрированных пользователей локальной сети - это можно. На сервере формируешь список айпишек подключенных пользователей и рассылаешь им нужное сообщение. Точно так же как и одному пользователю, только в цикле.
 #11  marishkin66 © 15.12.04 13:20:50

Да. для локальной сети. а как узнать ip-адреса подключенных клиентов? как отправить сообщение клиенту с определенным адресом?
 #12  marishkin66 © 15.12.04 13:35:55

Вот с первой частью своего же вопроса разобралась: для определения используется AThread.Connection.Socket.Binding.PeerI­P
 #13 Паша © 15.12.04 13:41:49

а сообщение по другому и не отправишь. токо в определенный АП-адрес. примеры пришли? там все достаточно популярно изложено
 #14  marishkin66 © 15.12.04 13:45:26

да пришли, ну там же про вин сокеты все... =( а нужно обязательно через idTCPClient/idTCPServer...
 #15 Паша © 15.12.04 13:46:59

ну и что? идея-то одинакова. просто свойства в твоих компонентах инди другие, видимо. так по ним надо хелп посмотреть
 #16 Deep © 15.12.04 13:47:14

>  #12 marishkin66 ©
мне кажется, тебе было бы проще скачать готовый чат и разобраться в его коде. А потом просто подкоректировать прогу в нужных местах по своему вкусу и цвету.
 #17  marishkin66 © 15.12.04 14:02:47

Deep! Так уже двое суток ищу исходники готового чата!! Или ищу плохо или что-то одно из двух... нету... только на сокетах или на UDP... =((
 #18  marishkin66 © 15.12.04 15:54:35

Может у кого есть примерчик самого простенького чата на основе IdTCPClient/IdTCPServer?  
 #19 Паша © 15.12.04 15:59:23

+IdTCPServer&meta=

наслаждайся. не знаю, чего там, но почтитать есть что, на первый взгляд
 #20  marishkin66 © 15.12.04 16:32:32

забавно, вроде что-то есть
 #21 Deep © 15.12.04 16:32:32

>  #18 marishkin66 ©
не нравится, мне инди. Чесслово. Никогда им не пользовался. В ранних версиях глюков много было, а потом уже другими пакетами начал пользоваться. Разве это серьезно, если на официальном сайте   практически нет документации и примеров?
вообщем-то и тебе не рекомендую юзать именно Инди, или тебе дали задание сделать именно на нем?
 #22  marishkin66 © 15.12.04 17:03:50

=) вот прочтейший чат на indy без всего (работает )
клиент:
unit untClient;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  StdCtrls;
type
  TfmClient = class(TForm)
    IdTCPClient1: TIdTCPClient;
    Label1: TLabel;
    Label2: TLabel;
    mmAll: TMemo;
    edNick: TEdit;
    edMessage: TEdit;
    BtnSend: TButton;
    BtnConnect: TButton;

    procedure BtnSendClick(Sender: TObject);
    procedure BtnConnectClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TPackage = record
                 UserNick,
                 Txt : string[255];
  end;
  TClientOnReceive = class(TThread)
    private
    ActiveP: TPackage;
    procedure Action;
    protected
    procedure Execute;
    override;
  end;
var
  fmClient: TfmClient;
  ClientRecive: TClientOnReceive;

implementation

{$R *.dfm}
procedure TClientOnReceive.Action;
begin
  fmClient.mmAll.Lines.Add (ActiveP.UserNick + ' : ' + ActiveP.Txt);
end;

procedure TClientOnReceive.Execute;
begin
  while not Terminated do
  begin
    if not fmClient.IdTCPClient1.Connected then
      Terminate
    else
    try
      fmClient.IdTCPClient1.ReadBuffer(Active­P, SizeOf (ActiveP));
      Synchronize(Action);
    except
    end;
  end;
end;

procedure TfmClient.BtnSendClick(Sender: TObject);
var
  SendPackage : TPackage;

begin
  SendPackage.UserNick := edNick.Text;
  SendPackage.Txt := edMessage.Text;

  IdTCPClient1.WriteBuffer (SendPackage, SizeOf (SendPackage), true);
end;

procedure TfmClient.BtnConnectClick(Sender: TObject);
begin
 try

      IdTCPClient1.Port := 12000;
      IdTCPClient1.Connect(10000);

      ClientRecive := TClientOnReceive.Create(True);
      ClientRecive.FreeOnTerminate:=True;
      ClientRecive.Resume;

    except
      on E: Exception do MessageDlg ('Ошбка соединения: '+#13+E.message, mtError, [mbOk], 0);
    end;
end;

end.
 #23  marishkin66 © 15.12.04 17:04:45

сервер:
unit untServer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdThreadMgr, IdThreadMgrDefault, IdBaseComponent, IdComponent,
  IdTCPServer, StdCtrls;

type


  WConnection   = ^TConnection;
  TConnection   = record
                Host        : string[20];
                Thread      : Pointer;
              end;
  TPackage = record
                 UserNick,
                 Txt : string[255];
  end;

  TfmServer = class(TForm)
    IdTCPServer1: TIdTCPServer;
    mmInf: TMemo;
    BtnStart: TButton;

    procedure IdTCPServer1Connect(AThread: TIdPeerThread);
    procedure IdTCPServer1Execute(AThread: TIdPeerThread);
    procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BtnStartClick(Sender: TObject);
    private
    { private declarations }
    public
    { public declarations }
  end;



var
  fmServer: TfmServer;
  ConnectionLst: TThreadList;

implementation

{$R *.dfm}


procedure TfmServer.IdTCPServer1Connect(AThread: TIdPeerThread);
var
NewConnection: WConnection;

begin
  GetMem(NewConnection, SizeOf(TConnection));
  NewConnection.Host        :=AThread.Connection.LocalName;
  NewConnection.Thread      :=AThread;
  AThread.Data:=TObject(NewConnection);

  try

    ConnectionLst.LockList.Add(NewConnectio­n);

  finally

    ConnectionLst.UnlockList;

  end;

  mmInf.Lines.Add('новое соединение:'+ NewConnection.Host+ ' ' +TimeToStr(Time));

end;

procedure TfmServer.IdTCPServer1Execute(AThread: TIdPeerThread);
var

  DestThread: TIdPeerThread;
  i: Integer;
  DestConnection: WConnection;
  Package, NewPackage: TPackage;
  
begin

  begin
    AThread.Connection.ReadBuffer (Package, SizeOf (Package));

        mmInf.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(NewPa­ckage, SizeOf(NewPackage), True);
          end;
        finally
          ConnectionLst.UnlockList;
        end;
      end;
end;


procedure TfmServer.IdTCPServer1Disconnect(AThrea­d: TIdPeerThread);
var
  ActiveConnection: WConnection;

begin
  ActiveConnection := WConnection(AThread.Data);
  try
    ConnectionLst.LockList.Remove(ActiveCon­nection);
  finally
    ConnectionLst.UnlockList;
  end;
  FreeMem(ActiveConnection);
  AThread.Data := nil;
end;

procedure TfmServer.FormCreate(Sender: TObject);
begin
ConnectionLst := TThreadList.Create;
end;

procedure TfmServer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  IdTCPServer1.Active := False;
  ConnectionLst.Free;
end;


procedure TfmServer.BtnStartClick(Sender: TObject);
begin
 IdTCPServer1.DefaultPort := 12000;
 IdTCPServer1.Active := True;
end;

end.

Я молодец?  
 #24 Паша © 15.12.04 17:07:29

>#21 Deep ©
я тоже  не пойму, зачем эти навороты, когда сокеты нормально работают... инди всякие...
 #25 Паша © 15.12.04 17:09:19

> Я молодец?
контрал+С, контрал+В? ай, маладца!
 #26  marishkin66 © 15.12.04 17:30:24

"контрал+С, контрал+В? ай, маладца! "
у-у-у я хоть понимаю, что написано...
 #27 Паша © 15.12.04 17:56:13

>#26 marishkin66 ©
шутю я, шутю
 #28  marishkin66 © 16.12.04 15:34:42

дополнение: как сделать, чтобы сообщения были разного цвета
В сервере и клиенте добавляем поле userColor : TColor в тип TPackage.

В клиенте заменяем компонент mmAll: TEdit на mmAll: TRichEdit и добавляем на форму компонент ColorBox1: TColorBox; (для выбора цвета текста)
Обрабатываем событие:
procedure TfmClient.ColorBox1Change(Sender: TObject);
begin
  edMessage.Font.Color:=ColorBox1.Selecte­d;
end;
в событие
procedure TfmClient.BtnSendClick(Sender: TObject);
добавляем  SendPackage.userColor := ColorBox1.Selected; (перед посылкой пакета)

в событие
procedure TClientOnReceive.Action;
добавляем
fmClient.mmAll.SelAttributes.Color := ActiveP.userColor;
  fmClient.mmAll.Lines.Add (ActiveP.UserNick + ' : ' + ActiveP.Txt);
  fmClient.mmAll.Refresh;

ВСЕ
 #29 Deep © 16.12.04 16:10:52

>  #28 marishkin66 ©
можешь еще сделать флажок приватных сообщений. Т.е. когда сообщение посылается конкретному участнику: он видит посланое сообщение, а другим пишется, что мол "двое таких то товарищей шепчутся по-секрету".
 #30  marishkin66 © 17.12.04 17:46:37

флажок приватных сообщений.
Сделала
И список пользователей добавила
А на сервере отражается если кто новенький пришел или если ушел кто-нить (и когда)
 #31 старый маразматик 17.12.04 18:03:13

> а другим пишется, что мол "двое таких то товарищей шепчутся по-секрету"
ну, эт здря. не надо такого писать, нехорошо


>#30 marishkin66 ©
молодца. а список активных пользователей надо у каждого участника коференции шоб был
 #32 Deep © 17.12.04 18:07:07

>  #30 marishkin66 ©
ну... теперь можно и выложить где-нить исходники -- может кому-нить пригодятся. Если хочешь могу выложить на нашем сайте. Пиши письмо. Можешь и о себе немного написать.
 #33  marishkin66 © 20.12.04 10:24:02

Вот усовершенствованный код клиента и сервера TCP чата...
клиент:
unit untClient;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  StdCtrls, ExtCtrls, ComCtrls, Winsock;

type
  TfmClient = class(TForm)
    IdTCPClient1: TIdTCPClient;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    edNick: TEdit;

    edMessage: TEdit;       //ñòð&#2­38;êà ñîî&#225­;ùåí&#232­;ÿ
    edIP: TEdit;            //ñòð&#2­38;êà äëÿ ââî&#228­;à àäð&#229­;ñà
    BtnSend: TButton;       //êíî&#2­39;êà ïîñ&#251­;ëêè ñîî&#225­;ùåí&#232­;ÿ
    BtnConnect: TButton;    //êíî&#2­39;êà "Âîé&am­p;#242;è â ÷àò"
    BtnDisconnect: TButton; //êíî&#2­39;êà âûé&#242­;è èç ÷àò&#224­;
    ColorBox1: TColorBox;   //âûá&#2­38;ð öâå&#242­;à òåê&#241­;òà ñîî&#225­;ùåí&#232­;ÿ
    mmAll: TRichEdit;       //ìåì&#2­38; â êîò&#238­;ðîì âèä&#237­;û âñå ñîî&#225­;ùåí&#232­;ÿ îò âñå&#245­; ïîë&#252­;çîâ&#224­;òåë&#229­;é
    mmHwo: TListBox;        //ëèñ&#2­42; â êîò&#238­;ðîì âèä&#237­;û íèê&#232­; ïîë&#252­;çîâ&#224­;òåë&#229­;é
    CheckBox1: TCheckBox;   //ôëà&#2­30;îê äëÿ ïðè&#226­;àòí&#251­;õ ñîî&#225­;ùåí&#232­;é
    lbFor: TLabel;          //çäå&#2­41;ü îòì&#229­;÷åí&#238­; êîì&#243­; èìå&#237­;íî îòñ&#251­;ëàå&#236­; ïðè&#226­;àòí&#238­;å ñîî&#225­;ùåí&#232­;å



    procedure BtnSendClick(Sender: TObject);
    procedure BtnConnectClick(Sender: TObject);
    procedure ColorBox1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BtnDisconnectClick(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure mmHwoClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TPackage = record
                 UserNick, Who,
                 Txt : string[255];
                 userColor : TColor;

  end;

  TClientOnReceive = class(TThread)
    private
    ActiveP: TPackage;
    procedure Action;
    protected
    procedure Execute;
    override;
  end;

var
  fmClient: TfmClient;
  ClientRecive: TClientOnReceive;

implementation

{$R *.dfm}

function CharCount(InputStr: string; InputSubStr: char): integer;
//Ïîä&#2­41;÷¸ò êîë&#232­;÷åñ&#242­;âà âõî&#230­;äåí&#232­;é ñèì&#226­;îëà â ñòð&#238­;êå
var
  i: integer;
begin
  result := 0;
  for i := 1 to length(InputStr) do
    if InputStr[i] = InputSubStr then
      inc(result);
end;


procedure TClientOnReceive.Action;
var s, uname, from_name: String;
    i, pos_: integer;
begin

 s:=ActiveP.Who;
 // À çäå&#241­;ü ìû äîá&#224­;âëÿ&#229­;ì â ñïè&#241­;îê íîâ&#238­;ãî ïîë&#252­;çîâ&#224­;òåë&#255­; (åñë&#23­2; îí ïðè&#241­;îåä&#232­;íèë&#241­;ÿ, êîí&#229­;÷íî)
 if (Copy(s,1,2) = '#N') then
 begin
  fmClient.mmHwo.Clear;
  Delete(s,1,2);
  for i:=0 to CharCount(s,';')-1 do
   begin
    uname:=Copy(s,1,Pos(';',s)-1);
    fmClient.mmHwo.Items.Add(uname);
    Delete(s,1,Pos(';',s));
   end;

  fmClient.mmHwo.Items.Add(s);
 end else
 begin
  //Âûâ&#2­38;ä ñîî&#225­;ùåí&#232­;ÿ
  fmClient.mmAll.SelAttributes.Color := ActiveP.userColor;
  s:=ActiveP.Txt;
  if (Copy(s,1,2) = '#P') then  //ïðè&#2­26;àòí&#2­38;ãî
  begin
   Delete(s,1,2);
   uname:=Copy(s,1,pos(';',s)-1);
   Delete(s,1,pos(';',s));
   from_name:=Copy(s,1,pos(';',s)-1);
   Delete(s,1,pos(';',s));
   if((uname=fmClient.edNick.Text)or(from_­name=fmClient.edNick.Text))then
   fmClient.mmAll.Lines.Add (ActiveP.UserNick + ' (ïðè&#22­6;àòí&#23­8;å)' + ' : ' + s );
  end else  //ñîî&#2­25;ùåí&#2­32;å äëÿ âñå&#245­;
  fmClient.mmAll.Lines.Add (ActiveP.UserNick + ' : ' + ActiveP.Txt);
  fmClient.mmAll.Refresh;
 end;
end;

procedure TClientOnReceive.Execute;
begin
  while not Terminated do
  begin
    if not fmClient.IdTCPClient1.Connected then
      Terminate
    else
    try
      fmClient.IdTCPClient1.ReadBuffer(Active­P, SizeOf (ActiveP));
      Synchronize(Action);
    except
    end;
  end;
end;

procedure TfmClient.BtnSendClick(Sender: TObject);
//ïûò&#2­24;åìñ&#2­55; ïîñ&#235­;àòü ñîî&#225­;ùåí&#232­;å
var
  SendPackage : TPackage;
begin
 if(edMessage.Text='') then showmessage('Íå&#­226;îçì&#­238;æíî îòï&#240­;àâè&#242­;ü ïóñ&#242­;îå ñîî&#225­;ùåí&#232­;å!') else
 begin
  SendPackage.UserNick := edNick.Text;
  if(CheckBox1.Checked)then //åñë&#2­32; ïðè&#226­;àòí&#238­;å ñîî&#225­;ùåí&#232­;å-äî&#22­5;àâë&#25­5;åì âíà&#247­;àëå ñòð&#238­;êè ôëà&#230­;îê '#P' è èìå&#237­;à ïîë&#243­;÷àò&#229­;ëÿ-î&#24­2;ïðà&#22­6;èòå&#23­5;ÿ
     SendPackage.Txt := '#P'+mmHwo.Items[mmHwo.ItemIndex]+';'+S­endPackage.UserNick+';'+edMessage.Text else
  SendPackage.Txt := edMessage.Text;
  //óñò&#2­24;íàâ&#2­35;èâà&#2­29;ì öâå&#242­; ñîî&#225­;ùåí&#232­;ÿ
  SendPackage.userColor := ColorBox1.Selected;

  //ïàê&#2­29;òèê ñî ñâå&#233­; èíô&#238­;ðìà&#246­;èåé çàï&#232­;ñûâ&#224­;åì â áóô&#229­;ð êëè&#229­;íòà
  IdTCPClient1.WriteBuffer (SendPackage, SizeOf (SendPackage), true);
 end;
end;

 #34  marishkin66 © 20.12.04 10:24:42

procedure TfmClient.BtnConnectClick(Sender: TObject);
//ïûò&#2­24;åìñ&#2­55; ñîå&#228­;èíè&#242­;üñÿ
var SendPackage : TPackage;
begin
 if (edNick.Text='')then ShowMessage('Ââ&#­229;äèò&#­229;, ïîæ&#224­;ëóé&#241­;òà íèê.') else
 begin
  BtnSend.Enabled:=true;
  CheckBox1.Enabled:=true;
  try
      //óñò&#2­24;íàâ&#2­35;èâà&#2­29;ì ïîð&#242­; (ìîæ&#23­7;î ñâî&#229­; çíà&#247­;åíè&#229­;, íî, ìíå íðà&#226­;èòñ&#255­; 12)
      IdTCPClient1.Port := 12000;
      //óñò&#2­24;íàâ&#2­35;èâà&#2­29;ì õîñ&#242­;
      IdTCPClient1.Host:=edIP.Text;
      //ïûò&#2­24;åìñ&#2­55; íåñ&#234­;îëü&#234­;î ñåê&#243­;íä ñîå&#228­;èíè&#242­;üñÿ
      IdTCPClient1.Connect(10000);

      ClientRecive := TClientOnReceive.Create(True);
      ClientRecive.FreeOnTerminate:=True;
      ClientRecive.Resume;

      edNick.ReadOnly:=true;
      // Îòï&#240­;àâë&#255­;åì èìÿ íîâ&#238­;ãî ïîë&#252­;çîâ&#224­;òåë&#255­; ñåð&#226­;åðó
      SendPackage.UserNick := edNick.Text;
      IdTCPClient1.WriteBuffer (SendPackage, SizeOf (SendPackage), true);
    except
      on E: Exception do MessageDlg ('Îøá&#2­34;à ñîå&#228­;èíå&#237­;èÿ: '+#13+E.message, mtError, [mbOk], 0);
    end;
  end;
end;

procedure TfmClient.ColorBox1Change(Sender: TObject);
begin
  edMessage.Font.Color:=ColorBox1.Selecte­d;
end;

procedure TfmClient.FormCreate(Sender: TObject);
begin
end;

procedure TfmClient.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 if IdTCPClient1.Connected then    IdTCPClient1.WriteLn(edNick.Text) else
   IdTCPClient1.Disconnect;
end;

procedure TfmClient.BtnDisconnectClick(Sender: TObject);
begin
 //âûõ&#2­38;äèì èç ÷àò&#224­;
 if IdTCPClient1.Connected then
 begin
  IdTCPClient1.WriteLn(edNick.Text);
  IdTCPClient1.Disconnect;
 end;
  mmHwo.Clear;
  mmAll.Clear;
  edNick.Text:='';
  edMessage.Text:='';
  ColorBox1.Selected:=clBlack;
  edNick.ReadOnly:=false;
  BtnSend.Enabled:=false;
  CheckBox1.Enabled:=false;
  lbFor.Visible:=false;
end;

procedure TfmClient.CheckBox1Click(Sender: TObject);
begin
 if (CheckBox1.Checked) then
 begin
  if mmHwo.ItemIndex=-1 then  mmHwo.ItemIndex:=0;
  lbFor.Visible:=true;
  lbFor.Caption:='Äë&am­p;#255; '+mmHwo.Items[mmHwo.ItemIndex];
 end else
 begin
  mmHwo.ItemIndex:=-1;
  lbFor.Visible:=false;
 end;
end;

procedure TfmClient.mmHwoClick(Sender: TObject);
begin
 if(CheckBox1.Checked)then
 begin
  if(mmHwo.ItemIndex>-1)then
  lbFor.Caption:='Äë&am­p;#255; '+mmHwo.Items[mmHwo.ItemIndex];
 end;
end;

end.
 #35  marishkin66 © 20.12.04 10:25:24

упс... что-то не то с русскими буквами =((
 #36  marishkin66 © 20.12.04 10:27:54

ладно, теперь сервер:
unit untServer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdThreadMgr, IdThreadMgrDefault, IdBaseComponent, IdComponent,
  IdTCPServer, StdCtrls;

type


  WConnection   = ^TConnection;
  TConnection   = record
                Host        : string[20];
                Thread      : Pointer;
              end;
  TPackage = record
                 UserNick,  Who,
                 Txt : string[255];
                 color_ : TColor;
  end;

  TfmServer = class(TForm)
    IdTCPServer1: TIdTCPServer;
    mmInf: TMemo;
    BtnStart: TButton;
    mmWho: TMemo;

    procedure IdTCPServer1Connect(AThread: TIdPeerThread);
    procedure IdTCPServer1Execute(AThread: TIdPeerThread);
    procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BtnStartClick(Sender: TObject);
    private
    { private declarations }
    public
    { public declarations }
  end;



var
  fmServer: TfmServer;
  ConnectionLst: TThreadList;

implementation

{$R *.dfm}
function CntRecurrences(substr, str : string): integer;
// ïîä&#241­;÷èò&#224­;òü êîë&#232­;÷åñ&#242­;âî âõî&#230­;äåí&#232­;é ïîä&#241­;òðî&#234­;è â ñòð&#238­;êó
var cnt, p : integer;
begin
 cnt := 0;
 while str <> '' do begin
  p := Pos(substr, str);
  if p > 0 then inc(cnt) else p := 1;
  Delete(str, 1, (p+Length(substr)-1));
 end;
 Result := cnt;
end;


procedure TfmServer.IdTCPServer1Connect(AThread: TIdPeerThread);
var
 NewConnection: WConnection;
 Package, NewPackage: TPackage;
 DestConnection: WConnection;
 DestThread: TIdPeerThread;
 i:integer;
 s, ss :string;
begin
  GetMem(NewConnection, SizeOf(TConnection));
  NewConnection.Host        :=AThread.Connection.LocalName;
  NewConnection.Thread      :=AThread;
  AThread.Data:=TObject(NewConnection);
  try
    ConnectionLst.LockList.Add(NewConnectio­n);
  finally
    ConnectionLst.UnlockList;
  end;

 AThread.Connection.ReadBuffer (Package, SizeOf (Package));

 mmInf.Lines.Add('&#202; &#237;&#224;&#236; &#239;&#240;&#232;&#248­;&#229;&#235;:'+ Package.UserNick + ' ' +TimeToStr(Time));
 mmWho.Lines.Add(Package.UserNick);

 s:='#N';
 //&#244;&#238;&#240;&#2­36;&#232;&#240;&#243;&#2­29;&#236; &#241;&#239;&#232;&#241­;&#238;&#234; &#226;&#241;&#229;&#245­; &#239;&#238;&#235;&#252­;&#231;&#238;&#226;&#224­;&#242;&#229;&#235;&#229­;&#233;
 for i:=1 to   mmWho.Lines.Count-1 do
 begin
   ss:=mmWho.Lines[i];
   //Delete(ss, length(ss)-6, 7);
   s:= s + ss + ';';
 end;
   Delete(s, length(s), 1);

 //&#206;&#242;&#241;&#2­51;&#235;&#224;&#229;&#2­36; &#237;&#238;&#226;&#238­;&#236;&#243; &#239;&#238;&#235;&#252­;&#231;&#238;&#226;&#224­;&#242;&#229;&#235;&#254­; &#241;&#239;&#232;&#241­;&#238;&#234; &#226;&#241;&#229;&#245­; &#239;&#238;&#235;&#252­;&#231;&#238;&#226;&#224­;&#242;&#229;&#235;&#229­;&#233;
 Package.Who:=s;


 //&#206;&#242;&#241;&#2­51;&#235;&#224;&#229;&#2­36; &#226;&#241;&#229;&#236­; &#241;&#239;&#232;&#241­;&#238;&#234; &#226;&#241;&#229;&#245­; &#239;&#238;&#235;&#252­;&#231;&#238;&#226;&#224­;&#242;&#229;&#235;&#229­;&#233;

 NewPackage := Package;
 with ConnectionLst.LockList do
     try
      for i := 0 to Count-1 do
       begin

          DestConnection := Items[i];
          DestThread := DestConnection.Thread;
          DestThread.Connection.WriteBuffer(NewPa­ckage, SizeOf(NewPackage), True);
       end;
      finally
       ConnectionLst.UnlockList;
    end;
end;

procedure TfmServer.IdTCPServer1Execute(AThread: TIdPeerThread);
var

  DestThread: TIdPeerThread;
  i: Integer;
  s, uname: string;
  DestConnection: WConnection;
  Package, NewPackage: TPackage;

begin

   AThread.Connection.ReadBuffer (Package, SizeOf (Package));
   mmInf.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(NewPa­ckage, SizeOf(NewPackage), True);
        end;
       finally
        ConnectionLst.UnlockList;
     end;


end;
 #37  marishkin66 © 20.12.04 10:28:19

procedure TfmServer.IdTCPServer1Disconnect(AThrea­d: TIdPeerThread);
var
  ActiveConnection: WConnection;
  Package, NewPackage: TPackage;
  i: integer;
  s, ss:string;
  DestConnection: WConnection;
 DestThread: TIdPeerThread;
begin
  ActiveConnection := WConnection(AThread.Data);
  try

    ss:= AThread.Connection.ReadLn;
    mmInf.Lines.Add('&#205;&#224;&a­mp;#241; &#239;&#238;&#234;&#232­;&#237;&#243;&#235;: '+ss +' '+TimeToStr(Time));

     for i:=1 to   mmWho.Lines.Count-1 do
     begin
      s:= mmWho.Lines[i];

      if (ss=s) then

      begin
       mmWho.Lines.Delete(i);
       mmWho.Refresh;
       break;
      end;
     end;

  //&#240;&#224;&#241;&#2­41;&#251;&#235;&#224;&#2­29;&#236; &#241;&#239;&#232;&#241­;&#238;&#234; &#239;&#240;&#232;&#241­;&#243;&#242;&#241;&#242­;&#226;. &#226; &#247;&#224;&#242;&#229­;

 s:='#N';
 //&#244;&#238;&#240;&#2­36;&#232;&#240;&#243;&#2­29;&#236; &#241;&#239;&#232;&#241­;&#238;&#234; &#226;&#241;&#229;&#245­; &#239;&#238;&#235;&#252­;&#231;&#238;&#226;&#224­;&#242;&#229;&#235;&#229­;&#233;
 for i:=1 to   mmWho.Lines.Count-1 do
 begin
   ss:=mmWho.Lines[i];
   s:= s + ss + ';';
 end;
  Delete(s, length(s), 1);
  ConnectionLst.LockList.Remove(ActiveCon­nection);
  finally
    ConnectionLst.UnlockList;
  end;
  FreeMem(ActiveConnection);
  AThread.Data := nil;


 NewPackage.Who := s;
 with ConnectionLst.LockList do
     try
      for i := 0 to Count-1 do
       begin

          DestConnection := Items[i];
          DestThread := DestConnection.Thread;
          DestThread.Connection.WriteBuffer(NewPa­ckage, SizeOf(NewPackage), True);
       end;
      finally
       ConnectionLst.UnlockList;
    end;

end;

procedure TfmServer.FormCreate(Sender: TObject);
begin
  ConnectionLst := TThreadList.Create;
end;

procedure TfmServer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  IdTCPServer1.Active := False;
  ConnectionLst.Free;
end;


procedure TfmServer.BtnStartClick(Sender: TObject);
begin
 IdTCPServer1.DefaultPort := 12000;
 IdTCPServer1.Active := True;
end;

end.
 #38  marishkin66 © 20.12.04 10:30:44

вот... с комментариями, конечно, не совсем хорошо вышло... жаль
 #39 Deep © 20.12.04 11:56:44

>  #38 marishkin66 ©
это потому, что они у тебя в юникоде были. Нужно было исходники заархивировать и мне на мыло прислать.  
 #40  Kolio 05.04.05 10:28:45

кул хлопцы!!!
 #41 wagner 09.10.05 14:43:00

NewConnection.Host        :=AThread.Connection.LocalName;
Всегда возвращает имя сервера - как это обойти ?
 #42  Maximus © 10.10.05 10:07:15

to marishkin66 ©

Дай мне поюзать на анкетное мыло?
 #43 deep © 10.10.05 11:31:47

>  #41   wagner
> Всегда возвращает имя сервера - как это обойти ?

а что должно возвращать?
 #44 wagner 12.10.05 22:46:17

to deep - согласен !
идеологически правильно ... я не тот вопрос задал -
хочется получать имя клиента а не сервера !
Так как в дальнейшем проверяется как бы сказать

  if RecClient.DNS=CommBlock.ReceiverName then  
            begin
              RecThread:=RecClient.Thread;

соответствие между клиентом подключившимся и отправившим пакет !
 #45  Серый 14.10.05 10:51:32

Привет Марина. Не могла бы ты поделиться исходником чата, но так как я ещё младенец в этом деле, то желательно с комментариями. Заранее большое спасибо. x-grey(собачка)mail.ru
 #46 marishkin66 © 14.10.05 15:00:16

#45 Серый
Привет, Сергей! все исходники ты можешь найти в этом посте! ничго нового по чату я с тех пор не написала. удачи!
 #47  Dmitriy O. © 17.10.05 07:41:36

Возми исходники чата

И не парься. Воще локальный чат лутьше писать на основе если Delphi то БД Interbase. Т.к. есть возможность
1.Посылать отложенные сообщения
2.Посылать файлы
3.Смотреть сообщения

 #48 DpoHro 25.10.05 15:46:28

Вопрос следующего характера, подобная конструкция является неблокирующей, тоесть когда происходит чтение/запись на одном подключении блокируются остальные?
Вобщем мне то нужно написать чат который бы успешно обслуживал бы до 200-300 пользователей одновременно...
Такой подход пойдет?
 #49 Dmitriy O. © 26.10.05 07:55:43

Если писать чат с использованием БД типа Interbase то проблем не будет транзакции надо тока правильно выставить.
 #50 deep © 26.10.05 09:21:05

>    #48   DpoHro
>> подобная конструкция является неблокирующей,

насколько, я знаю для "неблокирующей конструкции" серверная компонента должна поддерживать многопоточность.
 #51 DpoHro 27.10.05 15:23:35

Ну Indy поддерживает!
 #52 deep © 27.10.05 16:17:31

>    #51   DpoHro
значит, блокировок не должно быть  
 #53 P.R. 10.11.05 19:26:18

Indy блокирует выполнение программы в рамках потока, обслуживающего одного клиента. Для каждого клиента - свой поток. Так что без граблей.
 #54 Knight © 15.11.05 14:25:42

Хорошо вам с серверами... :(
 #55 SargonRa 04.09.07 12:28:53

Изучаю делфи. Ну народ нет слов. Чаты забабахали.  




  • Написать ответ

    Имя: Регистрация HTML?
    smiles смайлики
    Потом перейти в:    
    паутина



      ©  webest.net, 2002-2007  

    top.mail.ru
    » Бесплатный счетчик посещений
    » Рейтинг сайтов