Форум: "Сети";
Текущий архив: 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