Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.06.2011, 21:14   #1
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
Восклицание Получение и отправка личных сообщений в чате через Socket (Тема закрыта))

Всем привет!
Народ, есть чат для локальной сети, реализованный через Socket-ы, личные сообщения в нем отображались раньше как и общие сообщение в одном компоненте (RichEdit), я реализовал личные сообщение так, что бы для каждого привата создавалось нова страница (как в аське или квипе), работаю с PageControl, в котором динамически создается компонент МЕМО.
Что бы решить эту проблему облазил весь форум, нашел парочку подходящих примеров, но к сожалению они ничем мне не помогли, можно сказать больше навредили .
И так, вот исходник кода, по которому при приеме Личных сообщений (ЛС), создается новая страница с именем клиента, приславшого ЛС.
Код:
procedure TForm2.SS2ClientRead(Sender: TObject; Socket: TCustomWinSocket);

    var
      b,j:integer;
      txt:string;
      x: Word;
      pn:integer;

      TabSheet: TTabSheet;
      ToolBar: TToolBar;
      Memo: TMemo;

// Если приватный пользователь Сервер
        Begin
           poss:=6;    // указываем начальный символ
           x:=0;       // обнуляем счетчик символов
           For j:=poss to len+1 do    // пробегаем по длине принятой строки
               Begin
                  x:=x+1;                 // записываем в счетчик сдвиг
                  If Copy(txt,j,1)=Chr(152) then        // если найден ключ (конец части ника в строке)
                           Begin
                             PrivateUser:=Copy(txt,poss,x-1);   // сохраняем ник приватного пользователя
                           end;
              end;
// Если приватный пользователь - сервер (Niks)
                     If PrivateUser=Niks then
        begin
//создаем страницу для привата
    TabSheet := TTabSheet.Create(Self);
    TabSheet.Caption := TUserList(Socket.Data).Name; //присваиваем странице имя клиента приславшого ЛС
    TabSheet.PageControl := PageControl1;
      Memo:= TMemo.Create(Self);
      Memo.Parent := TabSheet;
      Memo.Align := alClient;
      Memo.ReadOnly:=true;
      Memo.ScrollBars := ssVertical;
    ToolBar := TToolBar.Create(Self);
    ToolBar.Parent := TabSheet;
    ToolBar.Align := alTop;
     Memo.Lines.Add(Copy(txt,7+Length(PrivateUser),len-Length(PrivateUser)-1));             //выводим сообщение в МЕМО 
       end
           
          else     //если сообщение не для сервера
              Begin
         // создаем цикл перебора пользователей
                 For b:=0 to SS2.Socket.ActiveConnections-1 do
                      Begin
               // если пользователь найден
                         If TUserList(SS2.Socket.Connections[b].Data).Name=PrivateUser then
                             Begin
                       // отсылаем сообщение в канал приватного пользователя
                               SS2.Socket.Connections[b].SendText('3' +PrivateEdit.Text+Chr(152) +'['+TimeToStr(Time)+']  '+TUserList(Socket.Data).Name+':  '+Copy(txt,6,Length(txt)-5));
// Сбрасываем цикл
                               break;
                             end;
                       end;
               end;
   end;
В этом случае все происходит на ура, сообщения и принимаются сервером (если ЛС для него) и отправляются дальше, до конечного пункта назначения. Но есть одна очень значительная проблема в это случаи – когда приходит ЛС на сервер в первый раз от клиента то все ок, вкладка создается, но когда этот же пользователь присылает еще одно сообщение, то на сервере создается еще одна вкладка с таким же пользователем, что просто неприемлемо, необходимо чтобы открывалась уже существующая страница.

Последний раз редактировалось darek13; 12.06.2011 в 14:26. Причина: Тема решенная!
darek13 вне форума Ответить с цитированием
Старый 11.06.2011, 21:17   #2
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

Для того что бы такого не было, я создал перед приходом ЛС поиск по названию страниц в PageControl-e, если такая страница уже есть то вывести туда сообщение и сделать активной. Но после того как я реализовал поиск по страницам, мои все ЛС накрываются «быстро и бесшумно» . Т.е. если ЛС для сервера, при его отсылке с клиента, сервер вообще никаких эмоций не проявляет, ничего не создается и ничего не отображается, так же происходит с клиент-клиент, когда сообщение проходит через сервер для другого клиента, клиент которому предназначалось ЛС, его тоже никак не отображает.
Помогите советами или примерами реализации этой проблемы, вообще хоть чем-то, а то я уже все по-гуглил и результата тоже нет много обещающего.
За ранее Всем ОГРОМНОЕ СПАСИБО!
Вот исходник кода уже с поиском по страницам.
[CODE]
Код:
procedure TForm2.SS2ClientRead(Sender: TObject; Socket: TCustomWinSocket);

    var
      b,j:integer;
      txt:string;
      x: Word;
      pn:integer;

      TabSheet: TTabSheet;
      ToolBar: TToolBar;
      Memo: TMemo;

// Если приватный пользователь Сервер
        Begin
           poss:=6;    // указываем начальный символ
           x:=0;       // обнуляем счетчик символов
           For j:=poss to len+1 do    // пробегаем по длине принятой строки
               Begin
                  x:=x+1;                 // записываем в счетчик сдвиг
                  If Copy(txt,j,1)=Chr(152) then        // если найден ключ (конец части ника в строке)
                           Begin
                             PrivateUser:=Copy(txt,poss,x-1);   // сохраняем ник приватного пользователя
                           end;
              end;
              // Если приватный пользователь - сервер (Niks)
                     If PrivateUser=Niks then
               begin
                  if pagecontrol1.PageCount > 1 then
                    begin
                      for pn := 0 to PageControl1.PageCount - 1 do
                        begin
                          if pagecontrol1.Pages[pn].Caption = TUserList(Socket.Data).Name then
                            begin
                              PageControl1.ActivePageIndex:=pn;
     Memo.Lines.Add(Copy(txt,7+Length(PrivateUser),len-Length(PrivateUser)-1));
                           end
                           else 
        begin
//создаем страницу для привата
    TabSheet := TTabSheet.Create(Self);
    TabSheet.Caption := TUserList(Socket.Data).Name; //присваиваем странице имя клиента приславшого ЛС
    TabSheet.PageControl := PageControl1;
      Memo:= TMemo.Create(Self);
      Memo.Parent := TabSheet;
      Memo.Align := alClient;
      Memo.ReadOnly:=true;
      Memo.ScrollBars := ssVertical;
    ToolBar := TToolBar.Create(Self);
    ToolBar.Parent := TabSheet;
    ToolBar.Align := alTop;
     Memo.Lines.Add(Copy(txt,7+Length(PrivateUser),len-Length(PrivateUser)-1));             //выводим сообщение в МЕМО 
       end;
          end ;
     end 
          else     //если сообщение не для сервера
              Begin
         // создаем цикл перебора пользователей
                 For b:=0 to SS2.Socket.ActiveConnections-1 do
                      Begin
               // если пользователь найден
                         If TUserList(SS2.Socket.Connections[b].Data).Name=PrivateUser then
                             Begin
                       // отсылаем сообщение в канал приватного пользователя
                               SS2.Socket.Connections[b].SendText('3' +PrivateEdit.Text+Chr(152) +'['+TimeToStr(Time)+']  '+TUserList(Socket.Data).Name+':  '+Copy(txt,6,Length(txt)-5));
           // Сбрасываем цикл
                               break;
                             end;
                       end;
               end;
        end;
  end;

Последний раз редактировалось darek13; 11.06.2011 в 21:20.
darek13 вне форума Ответить с цитированием
Старый 11.06.2011, 22:45   #3
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

> я создал перед приходом ЛС поиск по названию страниц в PageControl-e

неа, вы создали цикл, это да. Но никак не поиск )

Поиск — это когда что-то ищут и находят (или не находят). И уже потом только принимают решение, создавать что-то новое (если не нашли) или активировать имеюшееся.

У вас же на каждой итерации цикла программа либо активирует какую-то страницу, если случайно наткнулась на то, что искала, или создаёт новую, если очередная страница не с искомым именем (при этом, PageControl1.PageCount увеличивается на 1, т.е. ваш цикл имеет мало шансов завершиться хоть когда-либо).

Вобще, в такой каше ещё и не такое можно наваять, создайте хотя бы отдельную функцию поиска индекса страницы по имени юзера:

Код:
function TForm2.GetPageControlPageIndexByUserName(const uname: string): Integer;
вам же потом с этим кодом жить дальше будет проще!
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 11.06.2011, 22:51   #4
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

veniside
а по подробней можно если не трудно, а то я как бы знаю как с функция работать, но как описать ее в этом случаи и внидрить затрудняюсь
darek13 вне форума Ответить с цитированием
Старый 11.06.2011, 22:59   #5
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

Код:
function TForm2.GetPageControlPageIndexByUserName(const uname: string): Integer;
var
  i: Integer;
begin
  result := -1;
  for i := 0 to PageControl1.PageCount - 1 do begin
    //
    if (PageControl1.Pages[i].Caption = uname) then begin
      //
      result := i;
      break;
    end;
  end;
end;
далее в SS2ClientRead() вызываем эту функцию:

Код:
pindex := GetPageControlPageIndexByUserName(TUserList(Socket.Data).Name);
if (0 <= pindex) then
  // активируем страницу с индексом pindex 
else
  // создаём новую страницу
;
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 11.06.2011, 23:38   #6
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

veniside
Я все так сдела, проект запустился без ошибки, но тока как отправляю с клиента любое сообщение будь то общие, ЛС для сервера или для другого клиента, то вывскакивает ошибка
Вот скрин ее
Изображения
Тип файла: jpg Безымянный.jpg (32.0 Кб, 49 просмотров)
darek13 вне форума Ответить с цитированием
Старый 11.06.2011, 23:51   #7
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

т.е. мы по адресу исключения в памяти должны догадаться, в какой именно строке оно происходит? Боюсь, вы переоцениваете наши телепатические возможности.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 12.06.2011, 00:08   #8
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

После нажатия ОК на ошибке оно польностью выделело
строку
Код:
if (0 <= pindex) then
darek13 вне форума Ответить с цитированием
Старый 12.06.2011, 00:08   #9
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

я могу проект выложить если надо
darek13 вне форума Ответить с цитированием
Старый 12.06.2011, 06:13   #10
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

Все Проблема решена! Всем спасибо!
darek13 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Отправка\получение смс через шлюз ОПСОСа Winter_Silence Общие вопросы .NET 1 20.09.2010 21:11
Отправка сообщений CalvinKlein Работа с сетью в Delphi 1 27.01.2010 20:46
Формат передаваемых данных хабам локальной сети, при отправке личных сообщений из DC клиетов docm Общие вопросы .NET 0 18.11.2008 15:33
рассылка сообщений всем пользователям в чате, протокол UDP RKS Работа с сетью в Delphi 14 15.12.2007 11:36
отправка сообщений Pitbull Работа с сетью в Delphi 6 03.08.2007 17:06