-
Передаю файл через сокеты. На сервере:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var ms:tmemorystream;
begin
if serversocket1.Socket.Connections[0].ReceiveText='get_file' then begin
showmessage('file------');
ms:= TMemoryStream.Create;
try
ms.LoadFromFile(PChar(maskedit1.Text));
ms.Position:= 0;
Socket.SendText(IntToStr(ms.Size) + #0);
Socket.SendStream(ms);
socket.SendText('#end_file#');
except
ms.Free;
end;
end;
end;
на кленте:
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var s, sl: string;
prov:bool;
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;
if copy(s,length(s)-9,10)='#end_file#' then begin
prov:=true;
end;
if s<>'#end_file#' then prov:=false;
try
if prov=false then Data.Write(s[1], length(s));
if prov=true then begin
if Data.Size = DataSize then
begin
Data.Position:= 0;
data.SaveToFile('c:\000.jpg');
Data.Free;
Reciving:= false;
showmessage('Файл принят');
end else showmessage('Файл принят не удачно');
end;
except
Data.Free;
end;
end;
Данные клиент получает, но не читает что ему пришло "#end_file#". Почему?
-
> не читает что ему пришло "#end_file#". Почему?
Потому что "#end_file#" ему не пришло.
-
Как сделать что-бы ему это пришло?
-
// Итак, осталось освободить поток, если что-то не так - не нужно На лицо работа с неблокирующими сокетами в блокирующей манере... непалучедся :)
-
> На лицо работа с неблокирующими сокетами в блокирующей манере. > .. непалучедся
Подкинте пожалуйста литературу(ссылок) про работа с блокированием и не блокированием.
-
Sergl (01.11.07 10:05) Данные клиент получает, но не читает что ему пришло "#end_file#". Почему? Объясняю: Socket.SendStream(ms); - послал только одну "пачку" данных до возникновения WOULBLOCK и вышел socket.SendText('#end_file#'); посылаешь маркер конца файла, но файл фактически не отправлен... т.к. оставшиеся "пачки" Stream досылаются по мере освобождения отправляющего буфера
-
-
Вместо socket.sendtext('#end_file#') дописать к ms, перед тем как отправить вот это ms.read('#end_file#',10);
Так пойдет?
-
Sergl (01.11.07 11:10) [7] Так пойдет? Ходьбой это не назавешь... Похромает...
-
Не хочет дописывать... ms.read('#end_file#',10); Как дописать?
-
Sergl (01.11.07 11:21) [9] Write :)
-
> Не хочет дописывать
А где ты дописываешь ? Нигде) read по-буржуйски - это читать, а не писать)
-
> Write :)
Извеняюсь за тупость:) Однако #end_file# так и не находит...
-
> DataSize:= StrToInt(sl);
С чего ты взял, что в sl находится строка, содержащая ожидаемок число, и ничего более кроме этого числа ?
-
-
> Для особотупых повторяю
Попрошу без хамства... За ссылку спасибо.
-
> С чего ты взял, что в sl находится строка, содержащая ожидаемок > число, и ничего более кроме этого числа ?
Я с сервера, перед отправкой файла, передаю вот это Socket.SendText(IntToStr(ms.Size) + #0); Я так думаю что клиент следующим сообщением получает ms.Size
-
Как, всетаки, дописать к моему потоку, перед отправкой, #end_file#. Так ms.write(#end_file#,10) - что то не работает
-
Ковычки забыл) - ms.write('#end_file#',10);
-
> клиент следующим сообщением получает ms.Size >
Может получить, а может и не получить.
TCP - протокол поточный, а не месседж-ориентированный, в нем нет разбиения на сообщения, данные передаются сплошным потоком.
-
Данные передаются партиями(я так понимаю), и что бы при передачи размера небыло лишнего сзади я ставлю #0. А чтобы небыло лишнего спереди я могу отсылать что-то вроде #start_file#
-
Как, всетаки, дописать к моему потоку, перед отправкой, #end_file#. Так ms.write(#end_file#,10) - что то не работает
-
> Данные передаются партиями(я так понимаю)
Неправильно понимаешь.
Данные передаются потоком.
-
Sergl © (01.11.07 12:57) [15] Попрошу без хамства... Че ты уперся в ms.write(#end_file#,10)? как ... на новые ворота... :) ms.write(PChar('#end_file#')^,10);
Sergl © (01.11.07 13:45) [20] Данные передаются партиями(я так понимаю) неправильно понимаешь... протокол поточный: т.е. один Send на другой стороне может разбится на несколько Recv и на оборот несколько Send могут слипнуться вызвав один Recv Отправив 10 "посылок" по Nбайт получатель получит от 1 "посылки" (размером N*10байт) до N*10 "посылок" (размером 1байт) причем каждый раз разного количества и размера :)
-
>Slym © Короче говоря тебе прийдется проверять сохранять все что тебе пришло в заранее подготовленном буфере(TMemoryStream подойдет)! Потом анализировать на нахождение нуля #0 в твоем буфере. Затем разбирать свой начало файла(его размер) и конец. Тебе выше объясняли, что TCP может прислать от 1 и до MaxBuf байт.(MaxBuf=8192 байт - хотя это тоже можно настроить! :) ). И вопрос нахрена тебе конец файла если ты посылаеш его длину? И зачем посылать текстовую длину файла, если можно заполнить структуру скажем: TFileRec=Record FileStart:String[10]; FileSize :Cardinal; ... End;
И проверять на наличие определенного(постоянного) размера данных в буфере приема? А то работа со строками это всегда гемор (по моему мнению)
-
Т.е.
... Data.Write(S,Length(s)); if not Reciving then begin // Теперь нам необходимо получить длину потока данных. SetLength(s, Data.Size); // +1 for the null terminator Data.Position:=0; Data.Read(s[1],Data.Size); _Size:=strlen(S)+1; StrLCopy(@sl[1], PChar(s), _Size); DataSize:= StrToInt(sl); Data:= TMemoryStream.Create;//это перенести в глобальный блок //здесь учесть что Data уже не пуст // Удаляем информацию о размере из данных. Delete(s, 1, Length(sl)); Reciving:= true; end;
|