Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Как реализовать список пользователей в чате.


Автор: ckazu 3.6.2006, 15:25
Приветствую.
У меня такая проблема:
Пишу чат на Delphi и не знаю как реализовать такую вещь как список пользователей(ников, тех кто сейчас в чате), как енто сделать? 

Автор: ВасяТриллер 3.6.2006, 16:26
А как ты узнаёшь о существовании собеседника? 

Автор: ckazu 3.6.2006, 16:38
Пока что никак, только если он сам напишет что нить в чате. Вот я и хочу чтобы было окно которое показывало бы чатовцев.... 

Автор: Mechanic 3.6.2006, 22:06
TListBox (без картинок), или TListView (если нужны иконки). 

Автор: Aleksiem 4.6.2006, 13:26
Я так и не понял в чём проблема: в интерфейсе (ты не можешь их отобразить) или в сетевом обмене информацией (можно увидеть только когда пользователь пошлёт сообщение. Если первый вариант, то опиши в чём именно проблема. Если второй, то при входе в чат можно посылать в сеть широковещательные пакеты со своими аттрибутами, кроме того можно каждые нцать секунд посылать пакет пинга, чтобы знать кто сейчас в чате а кто уже вышел, при выходе из чата должен посылаться пакет выхода со всеми аттрибутами. Вообще надо бы поподробней описать чат, на каком протоколе работает как происходит связь с клиентами. 

Автор: ckazu 4.6.2006, 23:00
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdUDPServer, IdBaseComponent, IdComponent, IdUDPBase,
  IdUDPClient, IdSocketHandle, Buttons, Menus, Sockets, WinSock, ExtCtrls;

type
  TMainForm = class(TForm)
    Memo: TMemo;
    Edit: TEdit;
    IdUDPClient: TIdUDPClient;
    IdUDPServer: TIdUDPServer;
    BitBtn: TBitBtn;
    Edit2: TEdit;
    Label1: TLabel;
    PopupMenu: TPopupMenu;
    N1: TMenuItem;
    Memo2: TMemo;
    IdUDPClient2: TIdUDPClient;
    IdUDPServer2: TIdUDPServer;
    procedure ButtonClick(Sender: TObject);
    procedure IdUDPServerUDPRead(Sender: TObject; AData: TStream;
      ABinding: TIdSocketHandle);
    procedure BitBtnClick(Sender: TObject);
    procedure N1Click(Sender: TObject);
    procedure IdUDPServer2UDPRead(Sender: TObject; AData: TStream;
      ABinding: TIdSocketHandle);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.ButtonClick(Sender: TObject);
begin
  IdUDPClient.Send(Edit.Text);
end;

procedure TMainForm.IdUDPServerUDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  StringFormatedStream: TStringStream;
    s: String;
begin
  StringFormatedStream:=TStringStream.Create('');
  StringFormatedStream.CopyFrom(AData, AData.Size);
  Memo.Lines.Add(StringFormatedStream.DataString);
  ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, s [1], Length(s));
  StringFormatedStream.Free;
end;

procedure TMainForm.BitBtnClick(Sender: TObject);
begin
  IdUDPClient.Send(Edit2.Text+' >  '+Edit.Text);
  Edit.Clear;
end;

function GetLocalIP: String;
const WSVer = $101;
var
  wsaData: TWSAData;
  P: PHostEnt;
  Buf: array [0..127] of Char;
begin
  Result := '';
  if WSAStartup(WSVer, wsaData) = 0 then begin
  if GetHostName(@Buf, 128) = 0 then begin
  P := GetHostByName(@Buf);
  if P <> nil then Result := iNet_ntoa(PInAddr(p^.h_addr_list^)^);
  end;
  WSACleanup;
  end;
end;

procedure TMainForm.N1Click(Sender: TObject);
begin
  IdUdpClient2.Send(GetLocalIP);
end;

procedure TMainForm.IdUDPServer2UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  StringFormatedStream: TStringStream;
  s: String;
begin
  StringFormatedStream:=TStringStream.Create('');
  StringFormatedStream.CopyFrom(AData, AData.Size);
  Memo2.Lines.Add(StringFormatedStream.DataString);
  ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, s [1], Length(s));
  StringFormatedStream.Free;
end;

end.

Вот чат, он самый простой. Я хочу чтобы там был просто список юзеров, как это правильнее сделать? 

Автор: Mechanic 5.6.2006, 00:19
Нет у меня такого компонента, но скорее всего, нужно в этой процедуре
Код

procedure TMainForm.IdUDPServerUDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);

вылавливать IP отправителя (из ABinding.PeerIP(?)), искать его в списке юзверей, и если нет, то добавлять.
Список юзверей можно в StringList (читай ListBox ;)) засунуть. 

Автор: ckazu 5.6.2006, 14:28
Если не сложно, напиши пожалуйста пример алгоритма, а то я Дельфи только начал и пока что ничего не знаю. 

Автор: Mechanic 6.6.2006, 23:41
Цитата(ckazu @  5.6.2006,  14:28 Найти цитируемый пост)
Если не сложно, напиши пожалуйста пример алгоритма

А я его уже написал..   smile 
А как это будет выглядеть в коде, нужно смотреть в доке на эти компоненты. У меня не все есть из этих компонентов, так что, прости, гипотезов не сочиняю..  smile 
 

Автор: Aleksiem 7.6.2006, 00:37
Как вариант можно вставить в процедуру создания формы, что-то типа 
IdUDPClient.Send('connect:' + GetLocalIP);
а в процедуре IdUDPServerUDPRead анализировать приходящие данные и создавать список пользователей,
и соответственно в процедуру OnClose вставить 
IdUDPClient.Send('disconnect:' + GetLocalIP);
и опять же в процедуре IdUDPServerUDPRead анализировать приходящие данные и очищать список пользователей от вышедших. Хотя способ не идеален (могут висеть мертвые пользователи), но для начала подойдёт. 

Автор: ckazu 7.6.2006, 21:51
Цитата(Aleksiem @ 7.6.2006,  00:37)
Как вариант можно вставить в процедуру создания формы, что-то типа 
IdUDPClient.Send('connect:' + GetLocalIP);
а в процедуре IdUDPServerUDPRead анализировать приходящие данные и создавать список пользователей,
и соответственно в процедуру OnClose вставить 
IdUDPClient.Send('disconnect:' + GetLocalIP);
и опять же в процедуре IdUDPServerUDPRead анализировать приходящие данные и очищать список пользователей от вышедших. Хотя способ не идеален (могут висеть мертвые пользователи), но для начала подойдёт.

Спасиба тебе, а не подскажешь как можно этот список сделать? Я вот думал через БазыДанных можно. 

Автор: Aleksiem 8.6.2006, 02:09
Цитата(ckazu @ 7.6.2006,  21:51)
Спасиба тебе, а не подскажешь как можно этот список сделать? Я вот думал через БазыДанных можно.

Честно говоря немного недоехал причём здесь базы данных. Всё можно сделать примерно следующим образом:
создаёшь ListBox (пусть будет lbUsers), в обработчике процедуры IdUDPServerUDPRead вставляешь примерно следующее
Код

var
 RecvStr: string; //строка пришедших данных
 User: string;
.....
begin
....
 If (Pos('connect:', RecvStr) = 1) then
 begin
  User := Copy(RecvStr, 1, 9);
  lbUsers.Items.Add(User);
  exit;
 end;
 If (Pos('disconnect:', RecvStr) = 1) then
 begin
  User := Copy(RecvStr, 1, 12);
  //здесь ищешь индекс строки содержащую строку User допустим индекс равен iDelete
 lbUsers.Items.Delete(iDelete);
 end;
.......
end;

Писал без делфи так что возможны мелкие ошибки. Примерно так  

Автор: ckazu 8.6.2006, 12:34
Не понял вот этого 
Код

//здесь ищешь индекс строки содержащую строку User допустим индекс равен iDelete
.
База данных для того чтобы ник запомнить. Наверное это можно сделать как то подругому, да? 

Автор: Aleksiem 10.6.2006, 03:08
Цитата(ckazu @ 8.6.2006,  12:34)
Не понял вот этого 
Код

//здесь ищешь индекс строки содержащую строку User допустим индекс равен iDelete
.
База данных для того чтобы ник запомнить. Наверное это можно сделать как то подругому, да?

Просто ищещь строку, содержащую имя выходящего из чата.
Примерно так 
Код

var 
 i: integer;
begin
.....
 For i := 0 to lbUsers.Items.Count-1 do
 begin
  If lbUsers.Items.Strings[i-1] = User then
  begin
   iDelete := i;
   break;
  end;
 end;
.....
end;

На выходе iDelete будет содержать индекс строки с текстом User, те с именем выходящего пользователя. 

Автор: Sinneren 17.1.2010, 14:47
сама реализация понятна, даже для других (вроде) способов(сокеты). 
я так понял товарищь хочет узнать, как клиент передаст информацию, содержащую свой ник, чтобы сервер это принял уже и там вписал во всякие листбоксы,разослал другим клиентам для их списка и т.п. уже.
так вот как получить этот ник с клиента, если тем же способом как и посылка сообщения (у сокетового чата), то он выведет в чат же всё передаваемое, пробовал отправку пакета через winsock, но там нужно у клиенты выставить тип blocking, пакет доходит, но не как строка и только до сервера(или клиента - уже не помню) и при этом режиме не удаётся посылать сабжи вообще.
 так как же передавать клиенту инфу о себе(ники и прочее)?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)