Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ClientSocket [D6, Win2k]


Страницы:   1 2 3 4

Dmitriy Polskoy ©   (2002-11-13 14:43:00) 

Подскажите, как сделать так, чтобы ClientSocket принимал ровно столько сколько передает ServerSocket. Объясняю - ServerSocket в
OnClientRead получает имя файла и затем передает его клиенту по 500 байт
AssignFile(SrcFile, FileName);
Reset(SrcFile,1);
try
repeat
BlockRead(SrcFile, Buffer, SizeOf(Buffer), BytesRead);
ServerSocket.Socket.Connections[0].SendBuf(Buffer, BytesRead);
until BytesRead = 0;
finally
CloseFile(SrcFile);
end;

А клиент принимет, но не 500 байт за раз, а другое число байт.
Я знаю, что это нормально, но как сделать, чтобы и принимал 500.
А то файл бьется.


stikriz   (2002-11-17 16:00:00) [1]

Дмитрий.
Вот тут недалеко есть такая ветка
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1035121869&n=4
А Ваша ошибка состоит в том, что Вы не знаете на самом деле сколько передано данных. Можно почитать ветку, которую я указал, но там есть тоже ошибка - помечать пакеты, а можно просто понять, что:
1) Это достаточно низкоуровневый механизм, поэтому что-то придется дополнительно предпринимать, чтобы все работало.
2) Эти компоненты просто посылают байтики и все. Остальное - Ваши проблеммы.
3) Надо как-то передавать клиенту к-во байтов, которые он должен принять.
4) Стараться не путать пакеты, т.е. пока передается файл, например, не передавать другие данные, а то все спутается.
5) Сколько возвращает ф-ция Receive... Столько и пришло, а остальное не потерялось - оно просто идет :-)

Итак, передали размер, и читайте, пока ве данные не выгребете и все... Нет никаких сложностей - только легкие неудобства.

Успехов, Николай.


Maksss   (2002-11-15 19:30:00) [2]

var Receiving : boolean;
DataSize :int64;
Data : TMemoryStream;

это приём:

procedure TClient1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var s: string;
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(file....

"это передача:

Data.LoadFromFile(OpenDialog1.FileName);
Data.Position:= 0;
ClientSocket1.Socket.SendText(IntToStr(Data.Size) + #0);
ClientSocket1.Socket.SendStream(Data);


Maksss   (2002-11-15 19:23:00) [3]

помоему глупо упиратся в размер ресива
не проще сначала передать размер файла а потом собирать весь ресив например в мемористреам


Dmitiy Polskoy   (2002-11-15 19:12:00) [4]

По поводу http://book.itep.ru/.Я это читал и даже книга у меня есть на эту тему. Вот сижу разбираюсь. Проблема в другом - программу мне здать надо скоро вот поэтому и прошу о помощи.


Dmitiy Polskoy   (2002-11-15 19:07:00) [5]

Ладно, сдаюсь. Кто-нибудь может мне ответить на один вопрос.
Когда именно возникает OnClientWrite. В следующем коде я пытаюсь
в этом обработчике сбрасывать значеник переменной в True. Но она так никогда и не збрасывается.
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
FileName := Socket.ReceiveText;
AssignFile(SrcFile, FileName);
Reset(SrcFile, 1);
try
repeat
if ok then
begin
if Res < BytesRead then
begin
Inc(Bufptr, Res);
BytesRead := BytesRead - Res;
Res := ServerSocket.Socket.Connections[0].SendBuf(Bufptr^, BytesRead);
if Res = -1 then
begin
Res := 0;
ok := false;
end;
Inc(SendSize, Res);
Label1.Caption := IntToStr(SendSize);
end;
BlockRead(SrcFile, Buffer, SizeOf(Buffer), BytesRead);
Bufptr := @Buffer[1];
Res := ServerSocket.Socket.Connections[0].SendBuf(Bufptr^, BytesRead);
if Res = -1 then
begin
Res := 0;
ok := false;
end;
Inc(SendSize, Res);
Label1.Caption := IntToStr(SendSize);
end
else if not ok then
begin
Exit;
Application.ProcessMessages;
Continue;
end;
until BytesRead = 0;
finally
CloseFile(SrcFile);
end;
end;

procedure TForm1.ServerSocketClientWrite(Sender: TObject;
Socket: TCustomWinSocket);
begin
ok:=true;
end;


savva   (2002-11-15 09:19:00) [6]

> Digitman © (14.11.02 17:42)
> Начни с http://books.itep.ru
точнее http://book.itep.ru/


Digitman   (2002-11-14 17:42:00) [7]


> Да потому, что не работал я с этим никогда.


Не работал ? Не берись за работу !
А если взялся - изучи прежде внимательнейшим образом всю документацию, относящуюся к теме.
И ведь исх.тексты от Борланда - всегда под рукой ! Ну неужели так трудно заглянуть в них и проанализировать, что делает в том или ином случае сам Борланд ? Чем? собственно, будет отличаться тот код, что ты от меня требуешь, от того что у тебя перед носом, в файле scktcomp.pas. Ничем абсолютно ! Я просто продублирую тебе его...

Начни с http://books.itep.ru

Там есть, imho, достаточно неплохие статьи по основам построения сетей и вполне сносное описание большей части спецификации Winsock - что, зачем, как работает и как следует применять.


Dmitriy Polskoy   (2002-11-14 17:36:00) [8]

Да потому, что не работал я с этим никогда. Пршу ведь тебя помоги написать, я когда увижу как это правильно делается хоть знать буду да рассуждать смогу.


Digitman   (2002-11-14 17:17:00) [9]

ладно, бросай на время рассуждения о "высоких материях"
у тебя даже приемник как положено рпботать не будет, а ты передачей озабочен

смотри сюда :


procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
FileName: string;
begin
FileName := Socket.ReceiveText; // (*)
... и т.д.


НА ОСНОВАНИИ ЧЕГО ты уверен, что после выполнения строчки (*) переменная FileName будет В ТОЧНОСТИ соответствовать тому, что послал передатчик ?


> И мне кажеться, что вызывая Send-метот внутри OnClientWrite,
> я рекурсивно вызываю этот самый OnClientWrite


НА ОСНОВАНИИ ЧЕГО тебе это кажется ?


Dmitriy Polskoy   (2002-11-14 17:10:00) [10]

Мне еще не понятно (опираюсь на последний мой код)где нужно вызывать BlockRead, после того, как я вышел из цикла в OnClientRead.


Dmitriy Polskoy   (2002-11-14 16:59:00) [11]

Вот на что спромогся. Поправь если что.

procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
FileName: string;
begin
FileName := Socket.ReceiveText;

AssignFile(SrcFile, FileName);
Reset(SrcFile,1);
try
repeat
BlockRead(SrcFile, Buffer, SizeOf(Buffer), BytesRead);
Res := ServerSocket.Socket.Connections[0].SendBuf(Buffer, BytesRead);
if (Res < BytesRead) or(Res = -1) then Exit;
until BytesRead = 0;
finally
CloseFile(SrcFile);
end;
end;

procedure TForm1.ServerSocketClientWrite(Sender: TObject;
Socket: TCustomWinSocket);
begin
if Res = BytesRead then Exit;

if Res = -1 then Res := 0;

bufptr := @Buffer[1];
Inc(bufptr, Res);
BytesRead := BytesRead - Res;

Res := ServerSocket.Socket.Connections[0].SendBuf(bufptr^, BytesRead);

if (Res < BytesRead) or (Res = -1) then Exit;

BlockRead(SrcFile, Buffer, SizeOf(Buffer), BytesRead);
Res := 0;

label1.Caption := inttostr(TotalSize);

end;


И мне кажеться, что вызывая Send-метот внутри OnClientWrite, я рекурсивно вызываю этот самый OnClientWrite


Digitman   (2002-11-14 16:09:00) [12]

каждая итерация будет требовать некий нач.адрес данных и их размер

если содержимое буфера передано не полностью, ReceiveBuf(addr = buffer, count = bufsize) вернет некое число Res >= 0.

это значит, что , раз буфер передан не полностью, очередной вызов ReceiveBuf() д.б. выполнен с параметрами

addr = buffer + Res
и
count = bufsize - Res

Это тоже непонятно ?


Dmitriy Polskoy   (2002-11-14 15:47:00) [13]

В буфере, который передается.


Digitman   (2002-11-14 15:41:00) [14]

в буфере чего ?


Dmitriy Polskoy   (2002-11-14 15:16:00) [15]

Я как в стену уперся - не могу понять и все. Покажи как это сделать - я увижу и запомню раз и навсегда.


Dmitriy Polskoy   (2002-11-14 15:06:00) [16]

А что если во время итерации предастся меньшее кол-во байт, чем в буфере?


Dmitriy Polskoy   (2002-11-14 15:01:00) [17]

Злой ты :-))


Digitman   (2002-11-14 14:59:00) [18]


> Dmitriy Polskoy


И не подумаю. Шевели мозгами, если ты программер, а не кодер.


Dmitriy Polskoy   (2002-11-14 14:56:00) [19]

Ну приведи пример пожалуста-а-а. Не пойму как кОдить и все.


Digitman   (2002-11-14 14:47:00) [20]

Да нежелательно вообще цикл в событии делать !!
Упомянутый мной цикл приемлем будет лишь для блок.режима, но у тебя-то - неблокирующий !

Пока ты циклишь передачу, ни одно событие не будет вызвано. Тем более, что после нескольких итераций ты будешь раз за разом получать отказ передачи блока - буфер передачи будет наполнен, и пока данные из него не будут физически отправлены, буфер не освободится. Что толку продолжать пытаться "толкать" в него очер.блок данных в итерации ?

Вызвал в какой-то итерации send-метод , получил отказ - зафиксируй где-либо вне обработчика события параметры отказавшей итерации и успокойся на этом, завершив обработку события.
Возникнет OnWrite - возобнови в его обработчике цикл с той итерации, на которой остановился и параметры которой запомнил.
Если же и в OnWrite после какой-то очередной send-итерации возник отказ - то же самое : запоминай параметры итерации и "успокойся", завершив обработку OnWrite, ибо оно возникнет снова и продолжишь в нем цикл с запомненной итерации. И так до тех пор , пока не будет достигнут последний шаг итерации


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо