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

Вниз

ClientSocket   Найти похожие ветки 

 
Dmitriy Polskoy   (2002-11-13 14:43) [0]

Подскажите, как сделать так, чтобы 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.
А то файл бьется.


 
Song   (2002-11-13 14:47) [1]

В приведённом примере не видно когда Вы делаете закрытие сокета.


 
F1   (2002-11-13 14:50) [2]

ClientSocket1.Socket.ReceiveBuf(buf,500); ???


 
Dmitriy Polskoy   (2002-11-13 14:56) [3]

Сокет я закрываю при закрытии клиента.
Кстати на небольших объемах (до 1 Мб) файл передается нормально,
а например, при файл в 170 Мб отправляется весь объем, а принимается меньше. Где он теряется?


 
Dmitriy Polskoy   (2002-11-13 15:01) [4]

2 F1 © (13.11.02 14:50)
Не получится, т.к в OnRead надо получить кол-во байт, которое пришло. Иначе опять будет сбой - файл оказывается в ~4 раза больше


 
Digitman   (2002-11-13 15:01) [5]


> как сделать, чтобы и принимал 500.


Принимай не более 500 байт за один раз. И всех делов.

см. function ReceiveBuf(var Buf; Count: Integer): Integer;

Count - сколько запросил для приема
Result - сколько реально принято

Result >= 0 , но Result < Count ?

Не проблема. Уменьшай Count на значение Result, смещай позицию в буфере на значение Result и повторяй в цикле, пока Count > 0. После этого передавай адрес цельного принятого блока в 500 байт на обработку.


 
F1   (2002-11-13 15:05) [6]

>Dmitriy Polskoy © (13.11.02 15:01)
>Не получится, т.к в OnRead...
А циклы начто???


 
Dmitriy Polskoy   (2002-11-13 15:07) [7]

2 Digitman © (13.11.02 15:01)
А как решить Dmitriy Polskoy © (13.11.02 15:01) и
если Result > Count?


 
F1   (2002-11-13 15:08) [8]

Result не может быть > Count!!!


 
Dmitriy Polskoy   (2002-11-13 15:10) [9]

2 all
Делаю так, а как надо?
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
begin
BytesRead := Socket.ReceiveLength;
Socket.ReceiveBuf(Buffer, BytesRead);
BlockWrite(DestFile, Buffer, BytesRead, BytesWritten);

sum := sum + bytesread;
label1.Caption := inttostr(sum);
end;


 
Dmitriy Polskoy   (2002-11-13 15:13) [10]

2 F1 © (13.11.02 15:08)
Да. Это я протупил.


 
F1   (2002-11-13 15:14) [11]

А тогда зачем тебе именно по 500 байт читать???
Или все-таки надо???


 
F1   (2002-11-13 15:16) [12]

Кстати Digitman уже много раз писал как ПРАВИЛЬНО передавать данные чере сокеты, поищи.


 
Dmitriy Polskoy   (2002-11-13 15:21) [13]

Да читал я. И вроде все работает, но на определенных размерах, а потом байты теряются. По 500 это непринципиально. Это число мой сервер будет определять исходя из размера файла.


 
F1   (2002-11-13 15:27) [14]

Попробуй так:
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
begin
BytesRead := Socket.ReceiveLength;
Res:=Socket.ReceiveBuf(Buffer, BytesRead);
BlockWrite(DestFile, Buffer, Res, BytesWritten);
sum := sum + Res;
label1.Caption := inttostr(sum);
end;

А то что Digitman раньше писал, точно работает!!!
Он по сетям хороший спец!!!


 
Dmitriy Polskoy   (2002-11-13 15:37) [15]

Все равно принимаю меньше чем отправляю.
Кстати, помоги найти то, что писал Digitman. Может я что-то не то читал.


 
F1   (2002-11-13 15:41) [16]

А покажи как отправляешь, может быть на самом деле и не отправляется все? Результат SendBuf анализируешь?


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

Отправляю так
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
FileName := Socket.ReceiveText;

AssignFile(SrcFile, FileName);
Reset(SrcFile,1);
try
repeat
BlockRead(SrcFile, Buffer, SizeOf(Buffer), BytesRead);
ServerSocket.Socket.Connections[0].SendBuf(Buffer, BytesRead);
sum := sum + bytesread;
label1.Caption := inttostr(sum);
until BytesRead = 0;
finally
CloseFile(SrcFile);
end;
end;

В Label отображается сколько отослал. На клиенте в Label - сколько принял. Значения не равны. Принятый файл действительно равен кол-ву байт, отображенном в label на клиенте, но ясное дело он битый.


 
F1   (2002-11-13 15:53) [18]

Конечно, проблема именно здесь!!!

ServerSocket.Socket.Connections[0].SendBuf(Buffer, BytesRead);
Может не послать!!! Он возврвщает количество на самом деле посланных или -1 при ошибке!!!
так что
sum := sum + ServerSocket.Socket.Connections[0].SendBuf(Buffer, BytesRead);
более реальная цифра, ты ее посмотри, тогда станет ясно, где ошибка!!!


 
Dmitriy Polskoy   (2002-11-13 16:01) [19]

Получается, что отсылает меньше, чем принимает. И как сделать, чтобы ServerSocket.Socket.Connections[0].SendBuf(Buffer, BytesRead) все правильно посылал.


 
F1   (2002-11-13 16:08) [20]

Отсылает меньше, чем принимает??? Опять чудеса!!!
Посмотри SendStream, Digitman его советовал использовать.
А если SendBuf, то посылать, пока в буфере есть место, и обрабатывать OnWrite.
Лучше поищи ветку, где Digitman все расписал, там тема была "Как правильно..." или что-то типа того.


 
F1   (2002-11-13 16:22) [21]

Так ведь рядом ветка!


 
Dmitriy Polskoy   (2002-11-13 18:29) [22]

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
res: integer;
begin
BytesRead := Socket.ReceiveLength;
Res := Socket.ReceiveBuf(Buffer, BytesRead);
if Res < BytesRead then ShowMessage("Error");
BlockWrite(DestFile, Buffer, BytesRead, BytesWritten);
end;
У меня выскакивает мое сообщенние в ShowMessage. Как исправить ошибку?


 
Dmitriy Polskoy   (2002-11-13 18:33) [23]

2 Digitman © (13.11.02 15:01)
А кусочком кода можно?


 
stikriz   (2002-11-13 19:49) [24]

Res := Socket.ReceiveBuf(Buffer, BytesRead);
if Res < BytesRead then ShowMessage("Error");
BlockWrite(DestFile, Buffer, BytesRead, BytesWritten);
end;

Это полный бред. BytesRead - это для того, чтобы не сделать буфер меньше, чем нужно, а Res - это реально скачанные данные. Часто, но не всегда они равны. И никакой ошибки нет, что Res меньше.

Николай.


 
s002156Shurik   (2002-11-14 01:11) [25]

Я принимаю так
if Socket.Connected then
begin
if Socket.ReceiveLength>0 then
rsz:=Socket.ReceiveBuf(buf,1024);
end;
понятно дело в цикле вернее в потоке но в данном случае это непринципиально rsz число реально принятых байт проверяю receivelength для того чтобы незапнуться при неожиданном дисконекте если в течении 10 секунд приходят пустые пакеты считаю разрывом по таймауту.
отправляю так:
при коннекте клиента определяю идентификатор сокета
SocHnd:=Socket.SocketHandle;
затем в потоке отсылаю данные через него тыже отсылаеш через конекшенс 0 что будет работать только если один клиент, стемже успехом при коннекте можеш использовать сокетом который передан в ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
и вешать свой сервер на одной задаче. а какже остальные клиенты? или по очереди?
Вобщем я в потоке перебираю все конекшенсы на предмет совпадения идентификатора сокета. и передаю нужному клиенту нужные данные.
for i:=0 to Form1.ServerSocket1.Socket.ActiveConnections-1 do
if Form1.ServerSocket1.Socket.Connections[i].SocketHandle=SoсHnd then
Form1.ServerSocket1.Socket.Connections[i].SendBuf(buf,1024);

простейший способ созданя много потокового сервера файлов это написание объекта на основе TTimer в который при рождении закинуть хандл сокета конекшенса и имя предаваемого файла а дальше запустить OnTime в котором он будет пересылать файл указанным выше способом.
Рождать такой объект нужно при коннекте клиент.
MyTimer:=TMyTimer.create(nil);
MyTimer.FileName:=Socket.recivetext;
MyTimer.SocHnd:=SocHnd:=Socket.SocketHandle;
MyTimer.Interval:=1;
MyTimer.enable:=true;
в OnTime первый раз открыть файл когда он закончится закрыть его
потом сделать дисконнект
for i:=0 to Form1.ServerSocket1.Socket.ActiveConnections-1 do
if Form1.ServerSocket1.Socket.Connections[i].SocketHandle=SoсHnd then
Form1.ServerSocket1.Socket.Connections[i].Disconnect(SocHnd);
и сделать
MyTimer.free;
все.
надеюсь поможет удачи.


 
Dmitriy Polskoy   (2002-11-14 09:23) [26]

2 stikriz (13.11.02 19:49)
Ни какой не бред. Если Res меньше, то остальные байты теряются. Мне надо сделать так, как говорит Digitman © (13.11.02 15:01), но я чето туплю и незнаю как это сделать.

2 s002156Shurik © (14.11.02 01:11)
Это не решает проблемы. Ну буду я получать в таймере, а сокет будет записывать меньше, чем получил. Смотри Digitman © (13.11.02 15:01)


 
Dmitriy Polskoy   (2002-11-14 09:57) [27]

Я делаю так, но что-то не работает

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
Res: integer;
begin
BytesRead := Socket.ReceiveLength;
Res := Socket.ReceiveBuf(Buffer, BytesRead);
BlockWrite(DestFile, Buffer, Res, BytesWritten);
BytesRead := BytesRead - Res;
while (BytesRead > 0) do
begin
FillChar(Buffer, SizeOf(Buffer), 0);
Res := Socket.ReceiveBuf(Buffer, BytesRead);
BlockWrite(DestFile, Buffer, Res, BytesWritten);
BytesRead := BytesRead - Res;
end;
end;



 
Dmitriy Polskoy   (2002-11-14 10:13) [28]

Еще пробовал так

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
Res, LastPos, Temp: integer;
begin
BytesRead := Socket.ReceiveLength;
Temp := BytesRead;
Res := Socket.ReceiveBuf(Buffer, BytesRead);
BytesRead := BytesRead - Res;
while (BytesRead > 0) do
begin
LastPos := LastPos + Res;
Res := Socket.ReceiveBuf(Buffer[LastPos+1], BytesRead);
if Res = -1 then Res := 0;
BytesRead := BytesRead - Res;
end;
BlockWrite(DestFile, Buffer, Temp, BytesWritten);
end;


 
Digitman   (2002-11-14 10:25) [29]


var
TotalBytesRead : Integer = 0;
Buffer : Pointer;
...

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
ActualBytesRead: Integer;
BytesRemainsToRead : Integer;
temp_bufptr: PChar;
begin
if ReceiveLength = 0 then Exit;
BytesRemainsToRead := 500 - TotalBytesRead;
temp_bufptr := Buffer;
Inc(temp_bufptr, TotalBytesRead);
ActualBytesRead := Socket.ReceiveBuf(temp_bufptr^, BytesRemainsToRead);
if ActualBytesRead >= 0 then
begin
Inc(TotalBytesRead, ActualBytesRead);
if TotalBytesRead = 500 then
begin
BlockWrite(DestFile, Buffer, TotalBytesRead,BytesWritten);
TotalBytesRead := 0;
end;
end;



 
Dmitriy Polskoy   (2002-11-14 10:38) [30]

А помоги с сервером. Я делаю так, но иногда сервер передает неправильное кол-во байт.


procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Res, LasrPos: Integer;
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);
while (Res = -1) do
begin
Sleep(1);
Res := ServerSocket.Socket.Connections[0].SendBuf(Buffer, BytesRead);
end;
sum := sum + Res;
label1.Caption := inttostr(sum);
until BytesRead = 0;
finally
CloseFile(SrcFile);
end;
end;


 
Digitman   (2002-11-14 10:50) [31]

Обратись к <V_Pavel>

Устал я уже писать одно и тоже.
Не далее как вчера он получил мылом работающий вариант передатчика с использованием SendStream.


 
Dmitriy Polskoy   (2002-11-14 10:53) [32]

2 Digitman © (14.11.02 10:25)
Не, не работает

> if ReceiveLength = 0 then Exit;

По-моему надо Socket.ReceiveLength


> BlockWrite(DestFile, Buffer, TotalBytesRead,BytesWritten);
>

А где же заполняется буфер
И что-то вообще не очень понятно. Если можешь объясни, а?


 
Dmitriy Polskoy   (2002-11-14 10:58) [33]

2 Digitman © (14.11.02 10:50)
Да написал я ему, а он молчит. Ну хоть ты не молчи.


 
Digitman   (2002-11-14 11:01) [34]


> По-моему надо Socket.ReceiveLength


Ну надо так надо. Несущественные ляпы сам исправляй.


> А где же заполняется буфер


А это что - по-твоему ?


ActualBytesRead := Socket.ReceiveBuf(temp_bufptr^, BytesRemainsToRead);



> И что-то вообще не очень понятно


Что непонятно ? Конкретно ?


 
Digitman   (2002-11-14 11:06) [35]

>Dmitriy Polskoy

Обратись к нему в форуме. Вообще-то я просил его выложить основные элементы программного решения на сайт.


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

2 Digitman © (14.11.02 11:01)
В таком случае надо
Buffer := temp_bufprt, а у тебя наоборот, или я, что-то не так понимаю.


 
Digitman   (2002-11-14 11:19) [37]


> Buffer := temp_bufprt


Зачем ?


temp_bufptr := Buffer; // получить указательна начало буфера
Inc(temp_bufptr, TotalBytesRead); // прибавить смещение



 
Dmitriy Polskoy   (2002-11-14 11:39) [38]

2 Digitman © (14.11.02 11:19)
Согласен
А помоги сервером, а то не получается никак. См. Dmitriy Polskoy © (14.11.02 10:38)


 
Digitman   (2002-11-14 12:15) [39]


> не получается никак.


Что не получается ?


 
Dmitriy Polskoy   (2002-11-14 12:29) [40]

Тоже, что и с клиентом - передает неправильное кол-во байт



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

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

Наверх




Память: 0.54 MB
Время: 0.009 c
7-49333
Koster
2002-11-04 09:31
2003.01.16
Физический доступ к носителю


4-49341
Ardor
2002-11-28 17:42
2003.01.16
Net Send


1-48975
ShaH
2003-01-06 15:12
2003.01.16
Как в проект Delphi подключить модуль написанный на C++ Builder e


14-49271
dRake
2002-12-27 12:01
2003.01.16
ASCII/ANSI


3-48895
VDenis
2002-12-20 11:13
2003.01.16
Как сделать





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский