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

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

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

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 03.06.2011, 18:46   #1
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
Восклицание Реализация многопоточного чата с возможностью передачи файлов по сети

Всем привет!!!!
Люди кто чем-то сможет помочь, то - "СТРАНА ГЕРОЕВ НЕ ЗАБУДЕТ! "
Я пишу диплом и скоро мне его сдавать, но есть ряд нерешенных проблем, и уж без Вас господа дело скорей всего совсем худо будет!
Значит так ознакомлю Вас, всех, с моими проблемами в проекте.
Для начала говорю сразу, скелет взят и статьи "Создание многопользовательского чата" сдесь же на форуме, вот это ссылкочка http://pblog.ru/?p=100 (надеюсь она добавилась), так же http://programmersforum.ru/showthread.php?t=12574. Но провел ряд небольших изменений, таких как разделил клиент и сервер на 2-е отдельные программы, на сервере убрал Таймер, все происходит в обработчике у сервера OnClientRead.
С самим чатом проблем нет.
Проблемы в следующем:
1) Необходимо отделить личные сообщения от общих, т.е. реализовать вкладки как в квипе или аське. Если быть точнее я добавил компонент PageControl и сделал одну вкладку с названием «Общий чат», так вот в нем должны отображаться только сообщения для всех пользователей, когда приходит личное сообщение как у клиента так и у сервера, необходимо что бы создавалась новая вкладка с названием того, от кого пришло это личное сообщение. Так же необходимо предусмотреть, если вкладка уже создана с пользователем, и от него приходит сообщение, то не надо что бы она создавалась еще раз, необходимо что бы на вкладке появлялась картинка в виде конверта (которая лежит в папке с файлами и наз. «пришло сооб» ). На форме есть кнопка «Создать вкладку» она реализует добавление новой вкладки с динамическим компонентом RichEdit. Но создание вкладок должно происходить автоматически, но при ее создание не надо что бы на нее сразу же переключалась, надо что бы постоянно была открытая только вкладка с Общим чатом, а на личные уже вручную переходить, когда будет отображаться иконка. Надо так же что бы была кнопка закрыть вкладку с личными сообщениями.
2) Вторая проблема заключается в том, что бы в Списке пользователей при нажатии правой кнопкой на ник можно было выбрать один из двух пунктов, просмотреть его IP-adres ( хоть в статье и было написано про то как узнать IP я к сожалению не догнал ((((( ) или отправить файл, само это контекстное меню которое выскакивает при нажатии на ник пользователя я реализовал, но надо сделать так что бы когда ты выбираешь свой ник и нажимаешь правой кнопкой, действий что бы никаких не было.
3) Эта проблема частично связана со второй, поскольку сама проблема заключается с передачей файлов. Она у меня реализована частично, т.е. файл посылается с клиента на сервер и все отлично происходит, проблемы в следующем:
- Почему то файл посылается размером не больше 11 Мб, пробовал послать серверу файл 18 Мб в конце при передачи файла, сервер глохнет, не знаю почему даже, необходимо что бы файл посылался хотя бы размером до 300 МБ.
- Сервер может принимать файл только от 1 клиента, если во время приема сервера файла, другой клиент шлет файл, сервер тоже зажмуривается.
- При приеме файла, сервер не отображает сообщение в чате, ни личное ни общие, радует что отправляет, но тоже не отображает его.
- Необходимо реализовать передачу файлов не только клиент – серверу (я смог реализовать только так) , а так же клиент-клиенту, и сервер-клиентам ( при посылки файла клиент-клиент, все действия должны проходить через сервер, т.ь. файл шлется сначала на сервер, в папку Хранилище Файлов, когда он его полностью примет, должен отослать его другому клиенту, которому этот файл предназначался, после чего с хранилища файл должен автоматически удалятся и отсылаться сообщение посылавшему клиенту что сообщение успешно доставлено , а когда файл предназначается серверу, он должен автоматически создавать папку с названием от кого пришел файл (ник клиента). Но через сервер должен проходить за раз не один файл как у меня, а что бы многопоточный режим был, я правда не знаю возможно ли такое в СОКЕТАХ.

Вот собственно и все, буду рад любой помощи и советам, и указанием мест в Исходниках об ошибках.

Исходники и архив с проектом конечно же прилагаются.

У кого вдруг не устоновлен компонент сокет, то неообходимо: выбрать меню: Component – Install Packages… – Add., далее нужно указать файл …\bin\dclsockets70.bpl.

!!!!!!!!!!!!!!!!!Буду благодарен очень тем, кто сможет потратить своё время на мой проект и помочь хочь чем-то!!!!!!!!!!!!!!
Вложения
Тип файла: rar ClientServer_.rar (785.3 Кб, 202 просмотров)

Последний раз редактировалось darek13; 03.06.2011 в 19:16. Причина: Уточнение
darek13 вне форума Ответить с цитированием
Старый 03.06.2011, 18:55   #2
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

Исходник Сервера

Код:
unit Unit2;
interface
.............
 private
    FName: string; // Имя файла
    FSize: integer; // Размер файла
    Receive: boolean; // Режим клиента
    MS: TMemoryStream; // Буфер для файла
  public
    { Public declarations }
  end;
type

  TUserList = class(TObject)
  public
    Name: ShortString;    // имя (ник)
    Image: Byte;          // индекс иконки
  end;

var

  Form2: TForm2;
  ContList: Byte;
  len, poss, x: Word;
  PrivateUser: String;
  Buf: array[0..3] of Byte;
  Niks: string;
  threadvar
  FontName, FontSize, FontColor: String;

implementation

uses Unit4, Unit1;

{$R *.dfm}

procedure TForm2.FormCreate(Sender: TObject);
begin
    TextEdit.Clear;
    ChatRichEdit.Lines.Clear;
// сообщение для всех
  PrivateEdit.Text:='Всем';

  Receive := false; // Режим приём команд
end;


procedure TForm2.FormShow(Sender: TObject);
var UItems: TListItem;
begin
      Niks:=Form1.NikEdit.Text;   {присваемый ник сервера по его логину}
      SS2.Port:=1313;             {запишем указанный порт в ServerSocket}
      SS2.Active:=True;           {запускаем сервер}

// добавим в ChatRichEdit сообщение с временем создания
// сразу зададим параметры шрифта (Arial, 8, красный, курсив)
      ShowColorMassage('00119['+TimeToStr(Time)+']  Сервер создан.', 2); {}
// изменяем тэг
      SpeedButton4.Tag:=1;{}
// меняем надпись клавиши
      SpeedButton4.Caption:='Закрыть сервер';

// очищаем список клиентов
  UserListView.Items.Clear;
// очищаем переменную
  UItems:=UserListView.Items.Add;
  UItems.Caption:=Niks;
  UItems.ImageIndex:=1;

end;


procedure TForm2.ShowColorMassage(msg: String; index: Byte);
var i:integer;
begin
// работаем с полем чата
  With ChatRichEdit do
    Begin
// переход на новую строку
      Lines.Add('');
// название шрифта, смотрим соответствие в списке
      SelAttributes.Name:=Form4.FontComboBox.Items.Strings[StrToInt(Copy(msg,2,1))];
// размер шрифта, смотрим соответствие в списке
      SelAttributes.Size:=StrToInt(Form4.SizeComboBox.Items.Strings[StrToInt(Copy(msg,3,1))]);
// цвет текста, смотрим соответствие в списке (не забываем про хитрость с десяткой)
      SelAttributes.Color:=Form4.ColorBox.Colors[StrToInt(Copy(msg,4,2))-10];
// условия применения стиля к тексту
      If index = 0 then SelAttributes.Style := [];        // обычный (сообщения)
      If index = 1 then SelAttributes.Style := [fsBold];  // полужирный (приват)
      If index = 2 then SelAttributes.Style := [fsItalic];  // курсив (системное)
// добавляем текст сообщение в поле чата, только его содержательную часть
      SelText:=Copy(msg,6,Length(msg)-5);
    end;
end;


procedure TForm2.UpdateUserList;
var i:integer;
    UItems: TListItem;
    StrUserList:string;
begin
// очищаем список клиентов
  UserListView.Items.Clear;
// очищаем переменную
  UItems:=UserListView.Items.Add;
  UItems.Caption:=Niks;
  UItems.ImageIndex:=1;
  StrUserList:=Niks+Chr(152);
  For i:=0 to SS2.Socket.ActiveConnections-1 do
  Begin
    if SS2.Socket.Connections[i].data<>nil then
    begin
      UItems:=UserListView.Items.Add;
      UItems.Caption:=TUserList(SS2.Socket.Connections[i].data).Name;
      UItems.ImageIndex:=TUserList(SS2.Socket.Connections[i].data).Image;
      StrUserList:=StrUserList+TUserList(SS2.Socket.Connections[i].data).Name+Chr(152);
    end;
  end;
  For i:=0 to SS2.Socket.ActiveConnections-1 do
  begin
    // отправим строку списка пользователей (код команды - 2)
    SS2.Socket.Connections[i].SendText('2'+StrUserList);
  end;

end;

procedure TForm2.SpeedButton4Click(Sender: TObject);
begin
If SpeedButton4.Tag=1 then
      Begin
// разрешаем обновление
      UpdateUserList;

// очищаем список клиентов
      UserListView.Items.Clear;
// закрываем сервер
      SS2.Active:=False;
// выводим сообщение в ChatRichEdit
// сразу зададим параметры шрифта (Arial, 8, красный, курсив)
      ShowColorMassage('00119['+TimeToStr(Time)+']  Сервер закрыт.', 2);
// возвращаем тэгу исходное значение
      SpeedButton4.Tag:=0;
// возвращаем исходную надпись клавиши
      SpeedButton4.Caption:='Включить сервер';
    end
  else
    Begin
// запишем указанный порт в ServerSocket
      SS2.Port:=1313;
// запускаем сервер
      SS2.Active:=True;
// добавим в ChatRichEdit сообщение с временем создания
// сразу зададим параметры шрифта (Arial, 8, красный, курсив)
      ShowColorMassage('00119['+TimeToStr(Time)+']  Сервер создан.', 2);
// изменяем тэг
      SpeedButton4.Tag:=1;
// меняем надпись клавиши
      SpeedButton4.Caption:='Закрыть сервер';
// разрешаем обновление
      UpdateUserList;

    end

end;
darek13 вне форума Ответить с цитированием
Старый 03.06.2011, 18:58   #3
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

Продолжение Исходника Сервера

Код:
 procedure TForm2.SendBitBtnClick(Sender: TObject);
    var
      i:integer;
  begin
    // если сообщение для всех
      If PrivateEdit.Text='Всем'
        then
          Begin
            // отправляем сообщение с сервера всем пользователям
              For i:=0 to SS2.Socket.ActiveConnections-1 do
                  Begin
                      SS2.Socket.Connections[i].SendText('0'+FontName  // 1 байт - шрифт
                                                            +FontSize  // 1 байт - размер
                                                            +FontColor // 2 байта - цвет
                                                            +'['+TimeToStr(Time)
                                                            +']  '+Niks
                                                            +':  '+TextEdit.Text);
                  end;
            // отобразим сообщение в ChatRichEdit
              ShowColorMassage('0'
                           +FontName
                           +FontSize
                           +FontColor
                           +'['+TimeToStr(Time)
                           +']  '+Niks
                           +':  '+TextEdit.Text, 0);
              TextEdit.Clear;
          end
            else
               Begin
                  // если выбран не свой  ник
                  If PrivateEdit.Text<>Niks
                    then
                        Begin
                          // создаем цикл поиска приватного пользователя
                            For i:=0 to SS2.Socket.ActiveConnections-1 do
                                Begin
                                // если пользователь найден
                                    If TUserList(SS2.Socket.Connections[i].Data).Name=PrivateEdit.Text
                                      then
                                        Begin
                                    // отсылаем сообщение в канал приватного пользователя
                                            SS2.Socket.Connections[i].SendText('3'
                                                                  +FontName
                                                                  +FontSize
                                                                  +FontColor
                                                                  +PrivateEdit.Text+Chr(152)
                                                                  +'>> ['+TimeToStr(Time)
                                                                  +']  '+Niks
                                                                  +':  '+TextEdit.Text);
                                  // отобразим сообщение в ChatRichEdit, приват ушел
                                            ShowColorMassage('3'
                                                                +FontName
                                                                +FontSize
                                                                +FontColor
                                                                +'<< ['+TimeToStr(Time)
                                                                +']  '+Niks
                                                                +':  '+TextEdit.Text, 1);

                                            TextEdit.Clear;
                                    // сбрасываем цикл

                                            break;
                                        end;
                                end;
                        end;
               end;
 end;


procedure TForm2.TextEditKeyPress(Sender: TObject; var Key: Char);
  begin
    If Key=#13 then SendBitBtn.Click;
  end;

procedure TForm2.SpeedButton5Click(Sender: TObject);
  begin
    ChatRichEdit.Clear;
  end;

procedure TForm2.UserListViewContextPopup(Sender: TObject;
  MousePos: TPoint; var Handled: Boolean);
  var
      li:TListItem;
begin
  li:=UserListView.GetItemAt(MousePos.X,MousePos.Y);
  if li=nil then
  begin
    Handled:=true;
  end;
end;
darek13 вне форума Ответить с цитированием
Старый 03.06.2011, 19:02   #4
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

Продолжение 2 Исходника Сервера

Код:
procedure TForm2.SS2ClientRead(Sender: TObject; Socket: TCustomWinSocket);

    var
      count,i,b,j,ind,z,sz:integer;
      com:Byte;
      FS:TFileStream;
      buf: Pointer;
      tmp,txt:string;
  begin
    Application.ProcessMessages;
    txt:=Socket.ReceiveText();
    if Receive
      then                                       // Если клиент в режиме приёма файла, то...
        Writing(Socket,txt)                      // Записываем данные в буфер
          else                                   // Если клиент не в режиме приёма файла, то...
            begin
                If txt<>'' then                  // условие, что пакет не пуст
            Begin
              com:=StrToInt(Copy(txt,1,1));      // получим код комманды
              len:=Length(txt)-1;                // получим длину строки

              Case com of                        // определение комманд
// код приема сообщения --------------------------------------------------------
                0: Begin
// добавим в ChatRichEdit сообщение клиента
                     ShowColorMassage(txt, 0);
// разошлем сообщение пользователям (кроме того, кто прислал)
                     For j:=0 to SS2.Socket.ActiveConnections-1 do
                       Begin
                         if Socket<>SS2.Socket.Connections[j] then
                            SS2.Socket.Connections[j].SendText(txt);
                       end;
                   end;
// -----------------------------------------------------------------------------
// код приема ника клиента -----------------------------------------------------
                1: Begin
// запишем в массив полученный ник
                     TUserList(Socket.Data).Name:=Copy(txt,2,len);
// отметим, что пользователь записан в список
                     TUserList(Socket.Data).Image:=0;
// обновляем список
                     UpdateUserList;
                   end;
// -----------------------------------------------------------------------------
// код приема приватного сообщения ---------------------------------------------
                3: Begin
// укажем начальный символ
                     poss:=6;
// обнулим счетчик символов
                     x:=0;
// пробегаем по длине принятой строки
                     For j:=6 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;
// если приватный пользователь - "сервер"
                     If PrivateUser=Niks then
                       Begin
// добавим в ChatRichEdit сообщение клиента
                         ShowColorMassage(Copy(txt,1,5)+Copy(txt,7+Length(PrivateUser),len-Length(PrivateUser)-1), 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(txt);
// сбрасываем цикл
                                 break;
                                  end;
                               end;
                           end;
                       end;

  4: Begin
      try
      MS := TMemoryStream.Create;                         // Создаём буфер для файла
      Delete(txt, 1, Pos('#', txt));                      // Определяем имя файла
      FName := Copy(txt, 0, Pos('#', txt) -1);            // Определяем имя файла
      Delete(txt, 1, Pos('#', txt));                      // Определяем размер файла
      FSize := StrToInt(Copy(txt, 0, Pos('#', txt) -1));  // Определяем размер файла
      Delete(txt, 1, Pos('#', txt)); // Удаляем последний разделитель
      Receive := true;                                    // Переводим сервер в режим приёма файла
      Writing(Socket,txt);                                // Записываем данные в буфер
              except
              end;

                   end;
// -----------------------------------------------------------------------------

               end;
            end;
        end;
    end;
darek13 вне форума Ответить с цитированием
Старый 03.06.2011, 19:03   #5
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

Продолжение 3 Исходника Сервера


Код:
procedure TForm2.SS2ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);

    var
      d:TUserList;
  begin
    // добавим в ChatRichEdit сообщение с временем подключения клиента
    // сразу зададим параметры шрифта (Arial, 8, красный, курсив)
        ShowColorMassage('00119['+TimeToStr(Time)+']  Подключился клиент.', 2);
    // разрешаем обновление
        d:=TUserList.Create;
        d.Name:='';
        d.Image:=0;
        Socket.Data:=TObject(d);
        Socket.SendText('1');

  end;

procedure TForm2.SS2ClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);

    var
      j,ind:integer;
  begin
    // добавим в ChatRichEdit сообщение с временем отключения клиента
    // сразу зададим параметры шрифта (Arial, 8, красный, курсив)
      ShowColorMassage('00119['+TimeToStr(Time)+']  Клиент отключился.', 2);
    // разрешаем обновление
      ind:=-1;
      For j:=0 to SS2.Socket.ActiveConnections-1 do
          Begin
              if Socket=SS2.Socket.Connections[j]
              then
                ind:=j;
          end;

        TUserList(Socket.Data).Free;
        Socket.Data:=nil;
        UpdateUserList;

  end;

procedure TForm2.SpeedButton3Click(Sender: TObject);
  begin
    // сообщение для всех
      PrivateEdit.Text:='Всем';
  end;


procedure TForm2.UserListViewDblClick(Sender: TObject);
  begin
    // если список пользователей не пустой и выделена запись
      If (UserListView.Items.Count>0) And (UserListView.SelCount>0)
        then
          Begin
            // запишем в поле "Кому" приватного пользователя
              PrivateEdit.Text:=UserListView.Selected.Caption;
          end;
  end;



procedure TForm2.Writing(Sock:TCustomWinSocket;Text: string);
begin
  if MS.Size < FSize then             // Если принято байт меньше размера файла, то...
  MS.Write(Text[1], Length(Text));    // Записываем в буфер
  // Выводим прогресс закачки файла
  PB.Position:= MS.Size*100 div fSize;
 //SB.SimpleText := 'Принято '+IntToStr(MS.Size)+' из '+IntToStr(Size);
  if MS.Size = FSize then            // Если файл принят, то...
  begin
    Receive :=false;                 // Переводим клиента в нормальный режим
    MS.Position := 0;                // Переводим каретку в начало буфера
    if not(DirectoryExists(ExtractFilePath(ParamStr(0)) + '\' + 'Хранилище Файлов'))
        then
          CreateDir(ExtractFilePath(ParamStr(0)) + '\' + 'Хранилище Файлов');
    MS.SaveToFile(ExtractFilePath(ParamStr(0)) + '\' + 'Хранилище Файлов\' + fName); // Сохраняем файл

    Sock.SendText('4');               // Посылаем команду "end", то есть файл принят
    MS.Free;                          // Убиваем буфер
    SB.SimpleText:= 'Файл принят';
  end;
end;


 // Добавление страниц в чате
procedure TForm2.Button1Click(Sender: TObject);
var
  TabSheet: TTabSheet;
  RichEdit: TRichEdit;
begin
  TabSheet := TTabSheet.Create(Self);
  TabSheet.Caption := 'Закладка 1';
  TabSheet.PageControl := PageControl1;

  RichEdit := TRichEdit.Create(Self);
  RichEdit.Parent := TabSheet;
  RichEdit.Align := alClient;

  RichEdit.Text := '123'

end;

end.
darek13 вне форума Ответить с цитированием
Старый 03.06.2011, 19:05   #6
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

ИСХОДНИК КЛИЕНТА

Код:
 private
    { Private declarations }
  public
    { Public declarations }
  end;



  Type
  TUserList = object
  Status: Byte;    // 1 - сервер, 2 - клиент
  Rec: Boolean;    // отметка записи пользователя в список
  Name: String;    // имя (ник)
  Image: Byte;     // индекс иконки
 end;


var
  Form2: TForm2;
  Nik:string;
  i, j, com, ContList: Byte;
  len, poss, x: Word;
  txt, StrUserList, PrivateUser: String;
  UpdDo: Boolean;
  Buf: array[0..3] of Byte;
  UserMas: array[0..255] of TUserList;
  UItems: TListItem;
  threadvar
  FontName, FontSize, FontColor: String;
  MS: TMemoryStream;
implementation

uses Font;

{$R *.dfm}


procedure TForm2.FormShow(Sender: TObject);
begin
      //Присваиваем названию формы и нику имя пользователи
      Nik:=Form1.Edit1.Text;
      Form2.Caption:=Nik;
    // запишем указанный порт в ClientSocket
     ClientSocket2.Port:=1313;
// запишем хост и адрес (одно значение HostEdit в оба)
     ClientSocket2.Host:=Form1.HostEdit.Text;
      ClientSocket2.Address:=Form1.HostEdit.Text;
// запускаем клиента
     ClientSocket2.Active:=True;
      Form1.Hide;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ClientSocket2.Close;
Form1.Close;
end;

procedure TForm2.ShowColorMassage(msg: String; index: Byte);
begin
// работаем с полем чата
  With ChatRichEdit do
    Begin
// переход на новую строку
      Lines.Add('');
// название шрифта, смотрим соответствие в списке
      SelAttributes.Name:=Form4.FontComboBox.Items.Strings[StrToInt(Copy(msg,2,1))];
// размер шрифта, смотрим соответствие в списке
      SelAttributes.Size:=StrToInt(Form4.SizeComboBox.Items.Strings[StrToInt(Copy(msg,3,1))]);
// цвет текста, смотрим соответствие в списке (не забываем про хитрость с десяткой)
      SelAttributes.Color:=Form4.ColorBox.Colors[StrToInt(Copy(msg,4,2))-10];
// условия применения стиля к тексту
      If index = 0 then SelAttributes.Style := [];        // обычный (сообщения)
      If index = 1 then SelAttributes.Style := [fsBold];  // полужирный (приват)
      If index = 2 then SelAttributes.Style := [fsItalic];  // курсив (системное)

// добавляем текст сообщение в поле чата, только его содержательную часть
      SelText:=Copy(msg,6,Length(msg)-5);
    end;
end;

procedure TForm2.ClientSocket2Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
// добавим в ChatRichEdit сообщение о соединении с сервером
// сразу зададим параметры шрифта (Arial, 8, красный, курсив)
  ShowColorMassage('00119['+TimeToStr(Time)+']  К серверу подключен.', 2);
end;

procedure TForm2.ClientSocket2Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
// добавим в ChatRichEdit сообщение о потере связи
// сразу зададим параметры шрифта (Arial, 8, красный, курсив)
  ShowColorMassage('00119['+TimeToStr(Time)+']  От сервера отключился.', 2);
end;

procedure TForm2.ClientSocket2Read(Sender: TObject;
  Socket: TCustomWinSocket);

  begin
      // получим текст, код комманды, длину строки

  txt:=Socket.ReceiveText();
  com:=StrToInt(Copy(txt,1,1));
  len:=Length(txt)-1;

// определение комманд
  Case com of
// добавим в ChatRichEdit сообщение с сервера
    0: ShowColorMassage(txt, 0){+strtmp2)};
// отошлем свой ник на сервер
    1: ClientSocket2.Socket.SendText('1'+Nik);
// примем строку списка пользователей
    2: Begin
// очищаем список клиентов
         UserListView.Items.Clear;
// добавим ключ конца строки (т.к. вырезка символов с задержкой)
         txt:=txt+Chr(152);
// укажем начальный символ
         poss:=2;
// обнулим счетчик символов
         x:=0;
// пробегаем по длине строки списка
         For j:=2 to len+1 do
           Begin
// записываем в счетчик сдвиг
             x:=x+1;
// если найден ключ (отделение ников в строке)
             If Copy(txt,j,1)=Chr(152) then
               Begin
// добавим в UserListView строку
                 UItems:=UserListView.Items.Add;
                 UItems.Caption:=Copy(txt,poss,x-1);
// укажем соответствующую иконку пользователя
                 If poss>2 then UItems.ImageIndex:=0
                      else
                          UItems.ImageIndex:=1;
// изменим текущую позицию в строке списка
                 poss:=j+1;
// обнулим счетчик символов
                 x:=0;
               end;
               end;
       end;
// добавим в ChatRichEdit приватное сообщение с сервера
    3: ShowColorMassage(Copy(txt,1,5)+Copy(txt,7+Length(Nik),len-Length(Nik)-1), 1);
    4: begin
         StatusBar1.SimpleText := 'Сервер принял файл';
         MS.Free; // Убиваем буфер
       end;
   end;

end;
darek13 вне форума Ответить с цитированием
Старый 03.06.2011, 19:05   #7
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

Продолжение Исходника Клиента

Код:
procedure TForm2.SendBitBtnClick(Sender: TObject);
var z:integer;
begin
 if TextEdit.Text<>'' then
 begin
// если сообщение для всех
      If PrivateEdit.Text='Всем' then
        Begin
// отправляем сообщение для всех
          ClientSocket2.Socket.SendText('0'
                                       +FontName
                                       +FontSize
                                       +FontColor
                                       +'['+TimeToStr(Time)
                                       +']  '+Nik
                                       +':  '+TextEdit.Text);
// отобразим сообщение в ChatRichEdit
          ShowColorMassage('0'
                           +FontName
                           +FontSize
                           +FontColor
                           +'['+TimeToStr(Time)
                           +']  '+Nik
                           +':  '+TextEdit.Text, 0);

              // очищаем TextEdit
                  TextEdit.Clear;
        end
      else
        Begin
// если выбран не свой ник
          If PrivateEdit.Text<>Nik then
            Begin
// отправляем приватное сообщение
              ClientSocket2.Socket.SendText('3'
                                           +FontName
                                           +FontSize
                                           +FontColor
                                           +PrivateEdit.Text+Chr(152)
                                           +'>> ['+TimeToStr(Time)
                                           +']  '+Nik
                                           +':  '+TextEdit.Text);

// отобразим сообщение в ChatRichEdit что кому-то отправлено приватное сообщение
              ShowColorMassage('0'
                               +FontName
                               +FontSize
                               +FontColor
                               +'<< ['+TimeToStr(Time)
                               +']  '+Nik
                               +':  '+TextEdit.Text, 1);

              // очищаем TextEdit
              TextEdit.Clear;
            end;

        end;
    end;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
// запишем указанный порт в ClientSocket
      ClientSocket2.Port:=1313;
// запишем хост и адрес (одно значение HostEdit в оба)
      ClientSocket2.Host:=Form1.HostEdit.Text;
      ClientSocket2.Address:=Form1.HostEdit.Text;
// запускаем клиента
      ClientSocket2.Active:=True;
end;

procedure TForm2.UserListViewDblClick(Sender: TObject);
begin
     // если список пользователей не пустой и выделена запись
  If (UserListView.Items.Count>0) And (UserListView.SelCount>0) then
    Begin
// запишем в поле "Кому" приватного пользователя
      PrivateEdit.Text:=UserListView.Selected.Caption;
    end;
end;

procedure TForm2.TextEditKeyPress(Sender: TObject; var Key: Char);
begin
  If Key=#13 then SendBitBtn.Click;
end;

procedure TForm2.SpeedButton5Click(Sender: TObject);
begin
ChatRichEdit.Clear;
end;

procedure TForm2.Button2Click(Sender: TObject);
var
 Size: integer;
 P: ^Byte;
begin
  if OD.Execute then
    begin
  MS := TMemoryStream.Create; // Создаём буфер для файла
  MS.LoadFromFile(OD.FileName);     {('C:\1.rar')} // Загружаем файл в буфер
  // Посылаем информацию о файл (команда # название # размер)
  ClientSocket2.Socket.SendText('4#'+ ExtractFileName(OD.FileName)+'#'+IntToStr(MS.Size)+'#');
  MS.Position := 0; // Переводим каретку в начало файла
  P := MS.Memory; // Загружаем в переменную "P" файл
  Size := ClientSocket2.Socket.SendBuf(P^, MS.Size); // Посылаем файл
  // Выводим прогресс
  //ProgressBar1.Position := Size*100 div MS.Size;
  //StatusBar1.SimpleText := 'Отправлено '+IntToStr(Size)+' из '+IntToStr(MS.Size)+' байт'
end;
end;

procedure TForm2.ClientSocket2Error(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
begin
 ShowMessage('Ошибка №' +  IntToStr(ErrorCode));    //Возникла ошибка
 ErrorCode :=0;                                     //игнор ошибки
end;


procedure TForm2.Button3Click(Sender: TObject);
begin
     ClientSocket2.Active:=False;
end;

procedure TForm2.UserListViewContextPopup(Sender: TObject;
  MousePos: TPoint; var Handled: Boolean);

 var
    li:TListItem;
  begin
        li:=UserListView.GetItemAt(MousePos.X,MousePos.Y);
  if li=nil then
  begin
    Handled:=true;
  end;
  end;

end.
darek13 вне форума Ответить с цитированием
Старый 03.06.2011, 19:37   #8
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,601
По умолчанию

Посмотри исходник. Может чем-то и поможет. Я давно его делал. Где-то там ошибки с массивами. Главное, попытка создания лички.(Выделяете галочками)
Все, чем могу помочь.
Вложения
Тип файла: zip New chat.zip (840.6 Кб, 151 просмотров)

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог
_PROGRAMM_ вне форума Ответить с цитированием
Старый 03.06.2011, 19:46   #9
darek13
Пользователь
 
Аватар для darek13
 
Регистрация: 27.04.2011
Сообщений: 68
По умолчанию

_PROGRAMM_

Спасибо за любую помошь, сейчас посмотри твой проект, может что то и подойдет )
darek13 вне форума Ответить с цитированием
Старый 03.06.2011, 19:56   #10
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,601
По умолчанию

Если хочешь файлы отправлять, вот держи. Если останется время, добавь эту возможность. Думаю, не помешает. Только перед началом сделай копию всего чата.
p.s. Картинку, которую передаю программой, рисовал не я
-- Add пересмотрел первый пост и увидел, что сервер у тебя передает файлы.
Когда у Вас диплом?
Цитата:
- Сервер может принимать файл только от 1 клиента, если во время приема сервера файла, другой клиент шлет файл, сервер тоже зажмуривается.
- При приеме файла, сервер не отображает сообщение в чате, ни личное ни общие, радует что отправляет, но тоже не отображает его.
Нужно создать, думаю, отдельный юнит с описанием потока. Туда добавить еще TserverSocket или TClientSocket(соответственно клиенту- клиент, серверу-сервер) и передавать файл. По-Моему мнению, этот способ решит многие проблемы.
Вложения
Тип файла: zip Send file.zip (467.7 Кб, 181 просмотров)

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог

Последний раз редактировалось _PROGRAMM_; 03.06.2011 в 20:03.
_PROGRAMM_ вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
передачи по сети файла Alar Работа с сетью в Delphi 4 07.02.2011 23:21
Ошибка конвертации при передачи фото по сети Lokos Работа с сетью в Delphi 2 07.10.2010 02:08
Локальные сети, алгоритм передачи данных Guliayka Помощь студентам 1 25.12.2009 16:26
помогомите написать програмку для передачи сообщений в локальной сети Илюха Работа с сетью в Delphi 6 20.11.2007 00:57