Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.01.16;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.023 c
1-49048
Stas_a
2003-01-08 06:34
2003.01.16
Компилирование


1-49018
Song
2003-01-07 12:53
2003.01.16
Проблема: на событии onCreate формы1 надо отобразить


14-49264
Jeka
2002-12-26 16:05
2003.01.16
Шрифт в Object Inspector


8-49169
Mihan
2002-05-23 16:22
2003.01.16
Как сделать авторан??


3-48909
korvin
2002-12-20 17:05
2003.01.16
Скролинг в локапе