Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Интернет и сети
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 23.05.2011, 00:18
Аватар для Crabber
Crabber Crabber вне форума
Прохожий
 
Регистрация: 14.10.2009
Сообщения: 8
Версия Delphi: 7
Репутация: 10
Восклицание Передача файлов через ServerSocket/ClientSocket

Возникли проблемы при передаче файлов jpg, bmp, mp3, exe от сервера клиенту. Сервер успешно принимает только текстовые файлы. При попытке принять мультимедийные и исполняемые файлы клиент выводит ошибки с несуразным бредом, в следствии чего принятый файл не пригоден для использования. Хотя размер файла при этом не отличается от размера файла который был передан сервером. Может кто подскажет каким образом можно реализовать передачу jpg, bmp, mp3, exe файлов с помощью данных компонетнов?

Тип сервера: stNonBlocking

Код сервера (отправка файла):

Код:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
   ms: TMemoryStream;
begin
  {Если от клиента пришла комманда серверу}
  client_msg:= Socket.ReceiveText;

  if client_msg = 'send' then
  begin
    ms:= TMemoryStream.Create;
  try
    ms.LoadFromFile('D:\1.exe');
    ms.Position:= 0;
    // Добавляем длину данных, чтобы клиент знал, сколько данных будет
    // передано. Добавляем #0 , чтобы можно было определить, где
    // заканчивается информация о размере.
    Socket.SendText(IntToStr(ms.Size) + #0);
    // Посылаем его
    Socket.SendStream(ms);
  except
      // освободить поток, если что-то не так.
      ms.Free;
  end;
end;


Код клиента (приём файла):

Код:
procedure TForm1.Button2Click(Sender: TObject);
begin
// Отправляем команду на сервер для начала передачи файла
ClientSocket1.Socket.SendText('send');
end;


procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  s, sl: String;
  Data: TMemoryStream;
  DataSize: Integer;
  Reciving: boolean;
begin
    s:= Socket.ReceiveText;
    if not Reciving then
    begin
      // получаем длину потока данных.
      SetLength(sl, StrLen(PChar(s))+1);
      StrLCopy(@sl[1], PChar(s), Length(sl)-1);
      DataSize:= StrToInt(sl);
      Data:= TMemoryStream.Create;
      Delete(s, 1, Length(sl));
      Reciving:= True;
    end;
    try
      Data.Write(s[1], length(s));
    if Data.Size = DataSize then
      begin
        Data.Position:= 0;
        Data.SaveToFile('C:\123.exe');
        Data.Free;
        Reciving:= False;
      end;
  except
     Data.Free;
  end;
end;

Последний раз редактировалось Admin, 23.05.2011 в 09:32.
Ответить с цитированием
  #2  
Старый 23.05.2011, 16:12
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Мне кажется, что прикол в том, что вы через String приём делаете, а строки и нулевые символы (которых в нетекстовых форматах уйма) - понятия несовместимые.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #3  
Старый 26.05.2011, 01:31
Аватар для Crabber
Crabber Crabber вне форума
Прохожий
 
Регистрация: 14.10.2009
Сообщения: 8
Версия Delphi: 7
Репутация: 10
По умолчанию

Кто нибудь может реализовать приём бинарных файлов через сокеты?
Ответить с цитированием
  #4  
Старый 26.05.2011, 09:38
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

один из вариантов:
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ScktComp;

type
  TForm1 = class(TForm)
    ServerSocket1: TServerSocket;
    ClientSocket1: TClientSocket;
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
  private
    { Private declarations }
    FPipeRead: THandle;
    FPipeWrite: THandle;
    FDataLen: DWORD;
    FDataRead: DWORD;
    FFileStream: TFileStream;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  CreatePipe(FPipeRead, FPipeWrite, nil, $8000);
  FDataLen:=0;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  CloseHandle(FPipeWrite);
  CloseHandle(FPipeRead);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ClientSocket1.Open;
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Memo1.Lines.Add('Client Connect');
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  FileStream: TFileStream;
  len: DWORD;
begin
  FileStream:=TFileStream.Create(Edit1.Text, fmOpenRead);
  try
    len:=FileStream.Size;
    ClientSocket1.Socket.SendBuf(len, SizeOf(len));
    ClientSocket1.Socket.SendStream(FileStream);
  except
    FileStream.Free;
  end;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  Len: Integer;
  Buffer: PChar;
  dummy: Cardinal;
begin
  Len:=Socket.ReceiveLength;
  Buffer:=GetMemory(Len);
  try
    Len:=Socket.ReceiveBuf(Buffer^, Len);
    WriteFile(FPipeWrite, Buffer^, Len, dummy, nil);
  finally
    FreeMemory(Buffer);
  end;
  while True do
  begin
    Len:=GetFileSize(FPipeRead, nil);
    if Len=0 then Break;
    if FDataLen=0 then
    begin
      if Len<SizeOf(DWORD) then Break;
      ReadFile(FPipeRead, FDataLen, SizeOf(DWORD), dummy, nil);
      FDataRead:=0;
      FFileStream:=TFileStream.Create(Edit2.Text, fmCreate);
    end else
    begin
      Buffer:=GetMemory(Len);
      try
        ReadFile(FPipeRead, Buffer^, Len, dummy, nil);
        FFileStream.Write(Buffer^, Len);
        Inc(FDataRead, Len);
        if FDataRead=FDataLen then
        begin
          FFileStream.Free;
          FDataLen:=0;
          Memo1.Lines.Add('Ok');
        end;
      finally
        FreeMemory(Buffer);
      end;
    end;
  end;
end;

end.

!!!Проверки и очистки ресурсов при дисконнекте нет!!!
Вложения
Тип файла: rar CloseSchool.rar (160.2 Кбайт, 406 просмотров)
__________________
Пишу программы за еду.
__________________

Последний раз редактировалось NumLock, 26.05.2011 в 09:41.
Ответить с цитированием
  #5  
Старый 27.05.2011, 12:13
Аватар для Crabber
Crabber Crabber вне форума
Прохожий
 
Регистрация: 14.10.2009
Сообщения: 8
Версия Delphi: 7
Репутация: 10
Хорошо

Спасибо, отличная реализация! Всё работает так-как и нужно было.
Ответить с цитированием
  #6  
Старый 27.05.2011, 13:10
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Crabber, да, забыл совсем предупредить: это только пример механизма (отправка размера данных-сами данные) получения двоичных данных по сокету. он не учитывает множественное подключение к серверу нескольких клиентов. в данном примере при подключении еще клиентов и отправки ими данных сервер в итоге получит "кашу". пример для работы с несколькими клиентами (на этом же механизме) я уже выкладывал ранее.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 00:37.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter