Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2002.12.19;
Скачать: [xml.tar.bz2];

Вниз

Передача данных через сокеты   Найти похожие ветки 

 
delpher_gray   (2002-10-20 17:51) [0]

Господа Делферы !
Подскажите почему "это" не работает ?

На приём:
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
s, sl: string;
begin
s:= Socket.ReceiveText;
if s[1] = "b" then
begin
Delete(s, 1, 1);
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 StatusBar.SimpleText := "Принято "+IntToStr(Data.Size)+" из "+IntToStr(DataSize);
if Data.Size = DataSize then
begin
Data.Position:= 0;
Image2.Picture.Bitmap.LoadFromStream(Data);
Data.Free;
Reciving:= false;
Socket.Close;
end;
except
Data.Free;
end;
end;
end;


На передачу:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
ms: TMemoryStream;
begin
if Socket.ReceiveText = "send" then
begin
ms:= TMemoryStream.Create;
try
Image1.Picture.Bitmap.SaveToStream(ms);
ms.Position:= 0;
Socket.SendText("b"+IntToStr(ms.Size) + #0);
Socket.SendStream(ms);
except
ms.Free;
end;
end;
end;


Тут сначала посылается знак "b", затем размер картинки, а затем сама картинка.
Файл принемается не до конца... Допишите код, если кто знает как это осуществить...


 
Polevi   (2002-10-20 19:51) [1]

очень советую ВНИМАТЕЛЬНО почитать хелп на WSAAsyncSelect


 
delpher_gray   (2002-10-21 11:17) [2]

Попробую...


 
Song   (2002-10-21 13:34) [3]

Напоминает переделанный пример из FAQ..


 
delpher_gray   (2002-10-21 15:48) [4]

to Song.
Даже очень напоминает :-)
Я просто хочу сделать так, чтоб файл не путался с другими командами...


 
Song   (2002-10-21 15:56) [5]

Не работает потому что не успевает передаться. Надо после SendStream() ждать команды от противоположного сокета, о том что файл принят и только после этого делать Socket.Close
Я тоже когда начинал делать переправку между клиентами файлами и сообщениями взял за пример этот отрывок из FAQ, но потом когда всё довелось до ума, от него мало чего осталось :-)


 
delpher_gray   (2002-10-22 11:27) [6]

!!!!!!!!!!!
to Song
Это не работает потому что инфай передаётся не в одном пакете, а в нескольких... Кажется я нашёл ошибку ;-)))
Я попробую дописать эту прогу, но если что-то будет не получатся, то ждите следующего вопроса !


 
Song   (2002-10-22 11:38) [7]

Инфа всегда_по_сети_передаётся_пакетами независимо от того какого размера файл (ну если только файл меньше размера пакета). Поэтому проблема не в том.


 
delpher_gray   (2002-10-22 13:01) [8]

Господа Делферы !
Я наконец-то понял как заставить эту прогу работать...
Вот так:
1. Сначала от клиента идёт команда серверу "send".
2. Когда сервер примет команду, он посылает: "b"+Размер файла+"Сам файл".
3. Если клиенту приходит эта команда, то он отделяет размер и записывает его в переменную DataSize, а сам файл пошет в Data (TMemoryStream).

В одном пакете не может же уместиться весь файл, нужно принять несколько пакетов... А вот чтоб определить что это кусок файла, а ни какая-нить команда, нужна как-то пометить пакеты (дописать перед пакетом "f").

Если вы подскажите как можно пометить пакеты, тогда нужно дописать:

4. Если в команде первый знак "f", то просто дописываем в Data кусок файла...

Вот так можно осуществить то что я зудумал ;-)
Но для этого нужно пометить пакеты...
Жду ответов, заранее благодарен.


 
YouNick   (2002-10-22 13:47) [9]

2Delpher_gray: Никак ... :(
Знаешь такой термин "конечный автомат"?
Вот для разбора принятых данных нужно создать что-то похожее.
Ведь ты в клиенте отправляешь один пакет (клиентская программа), а реально в сеть может уйти несколько пакетов (TCP их сам разбивает на реальные пакеты). Например, ты отправляешь 10000 байт одним пакетом, а принять можешь 10 пакетов по 1000 байт. Что в таком случае считать "командой"? И первый знак в твоей команде может совпасть с содержимым файла - "f". ТОгда ты в файл такого позаписываешь .... ;))) У мню где-то были классы, реализующие передачу файлов (серверная и клиентская часть), надо поискать. Если конечно интересует еще ;)


 
grvakh   (2002-10-22 14:06) [10]

На прием стоит - data.write
Где вообще data связывается с сокетом?


 
delpher_gray   (2002-10-22 15:07) [11]

Ммммм да... =/
И что же мне делать ??
Мне как-то нужно доделать этот код.
Ну как-нибудь можно же написать подобную прогу ?


 
delpher_gray   (2002-10-23 15:50) [12]

Ну тогда подскажите как можно написать подобную прогу ?


 
Song   (2002-10-23 16:15) [13]

Я говорю Вам, что всё работает и по Вашему вышеиложенному алгоритму только нужно довести до ума.
Вот примерный алгоритм:
Клиент:
1. Клиент посылает строку "header#file.txt#100#End"
2. Клиент посылает файл потоком
3. Инициирует цикл ожидания пока, например переменная Flag не станет True
4. Конец работы клиента

Сервер:
1. Сервер ловит данные. Проверяет есть ли "header".
2. Если нет, переходим на третий шаг. Если есть значит, это название файла. Создаёт в памяти экземпляр класса TMemoryStream (глобального для данного модуля) и заносит в переменную Limit например длину файла - 100 байт. Вырезает из строки начало до слова End включительно. Переходим на третий шаг.
3. Добавляем к экземпляру TMemoryStream полученную строку данных. Проверяем, не равно ли длина экземпляра переменной Limit. Если равно записываем поток в файл, уничтожаем экземпляр. Если не равно ничего не делаем, выходим из процедуры.

Вот и всё. Работает данный алгоритм стабильно. Сам делал.


 
Song   (2002-10-23 16:17) [14]

Забыл добавить что в 3 пункте сервера после того как файл запишем передаём команду на вызывающий хост, получив которую последний поднимет флажок Flag, благодаря чему вызывающий клиент выйдет из цикла и только потом закроет сокет.


 
delpher_gray   (2002-10-23 19:50) [15]

Song !
Я написал прогу так как Вы объяснили, но там если первые 4 символа не равны "file", то прога выдаёт ошибку...
Вот код сервера:
unit UServer;

interface

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

type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
StatusBar: TStatusBar;
procedure FormCreate(Sender: TObject);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.Open;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
MS: TMemoryStream;
S: string;
Sp: string;
Name: string;
Size: integer;
label Receive;
begin
S := Socket.ReceiveText;
Sp := Copy(S, 1, 4);
if Sp <> "file" then goto Receive;
if Sp = "file" then
begin
Delete(S, 1, 5);
Name := Copy(S, 1, Pos("#", S) -1);
Delete(S, 1, Length(Name) +1);
Size := StrToInt(Copy(S, 1, Pos("#", S) -1));
Delete(S, 1, Length(IntToStr(Size)) +4);
MS := TMemoryStream.Create;
Receive:
MS.Write(S[1], Length(S));
StatusBar.SimpleText := "Принято "+IntToStr(MS.Size)+" из "+IntToStr(Size);
if MS.Size = Size then
begin
MS.Position := 0;
MS.SaveToFile(Name);
Socket.SendText("end");
ServerSocket1.Close;
MS.Free;
end;
end;
end;

end.
Подскажите где я ошибся ;-)


 
Song   (2002-10-23 22:11) [16]

ЕЩЁ РАЗ ГОВОРЮ ПОЧЕМУ: (я уже говорил об этом в другом Вашем топике)
потому_что_MS_локальная_переменная
Она обнуляется при каждом возникновении события TServerSocket.onClientRead


 
delpher_gray   (2002-10-24 11:31) [17]

Огромное вам спасибо Song !
Я написал прогу, и она отлично работает...


 
Song   (2002-10-24 11:38) [18]

Ну и славно. Если Вы бы обратили внимание на мою реплику раньше, давно бы всё написали.



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2002.12.19;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.01 c
1-61556
viper
2002-12-09 15:54
2002.12.19
Размер файла


14-61784
Skier
2002-11-28 11:34
2002.12.19
Кто знает эту идею или алгоритм ?


14-61780
Grande
2002-11-27 10:11
2002.12.19
Кому-нибудь нужна книга по Delphi5?


1-61566
before
2002-12-09 18:36
2002.12.19
начальные знаниея .........Delphi7


1-61665
Tik
2002-12-08 07:01
2002.12.19
TreeView, StringGrid





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский