Форум: "Сети";
Текущий архив: 2008.10.12;
Скачать: [xml.tar.bz2];
Вниз
Не пойму где ошибка(сокеты)... Найти похожие ветки
← →
Sergl (2007-11-01 10:05) [0]Передаю файл через сокеты.
На сервере:
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;
// Добавляем длину данных, чтобы клиент знал, сколько данных будет передано
// Добавляем #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); // +1 for the null terminator
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
// showmessage("Ура");
prov:=true;
// Delete(s,length(s)-9,10);
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;
// Socket.Close;
showmessage("Файл принят");
end else showmessage("Файл принят не удачно");
end;
except
Data.Free;
end;
end;
Данные клиент получает, но не читает что ему пришло "#end_file#". Почему?
← →
Сергей М. © (2007-11-01 10:43) [1]
> не читает что ему пришло "#end_file#". Почему?
Потому что "#end_file#" ему не пришло.
← →
Sergl (2007-11-01 10:46) [2]Как сделать что-бы ему это пришло?
← →
Slym © (2007-11-01 10:59) [3]// Итак, осталось освободить поток, если что-то не так - не нужно
На лицо работа с неблокирующими сокетами в блокирующей манере... непалучедся :)
← →
Sergl (2007-11-01 11:04) [4]
> На лицо работа с неблокирующими сокетами в блокирующей манере.
> .. непалучедся
Подкинте пожалуйста литературу(ссылок) про работа с блокированием и не блокированием.
← →
Slym © (2007-11-01 11:04) [5]Sergl (01.11.07 10:05)
Данные клиент получает, но не читает что ему пришло "#end_file#". Почему?
Объясняю:
Socket.SendStream(ms); - послал только одну "пачку" данных до возникновения WOULBLOCK и вышел
socket.SendText("#end_file#");
посылаешь маркер конца файла, но файл фактически не отправлен... т.к. оставшиеся "пачки" Stream досылаются по мере освобождения отправляющего буфера
← →
Slym © (2007-11-01 11:08) [6]Sergl (01.11.07 11:04) [4]
Подкинте пожалуйста литературу(ссылок) про работа с блокированием и не блокированием.
http://delphimaster.net/view/6-1192377094/
← →
Sergl (2007-11-01 11:10) [7]Вместо socket.sendtext("#end_file#") дописать к ms, перед тем как отправить вот это ms.read("#end_file#",10);
Так пойдет?
← →
Slym © (2007-11-01 11:13) [8]Sergl (01.11.07 11:10) [7]
Так пойдет?
Ходьбой это не назавешь... Похромает...
← →
Sergl (2007-11-01 11:21) [9]Не хочет дописывать... ms.read("#end_file#",10);
Как дописать?
← →
Slym © (2007-11-01 11:22) [10]Sergl (01.11.07 11:21) [9]
Write :)
← →
Сергей М. © (2007-11-01 11:23) [11]
> Не хочет дописывать
А где ты дописываешь ? Нигде)
read по-буржуйски - это читать, а не писать)
← →
Sergl (2007-11-01 11:24) [12]
> Write :)
Извеняюсь за тупость:)
Однако #end_file# так и не находит...
← →
Сергей М. © (2007-11-01 11:49) [13]
> DataSize:= StrToInt(sl);
С чего ты взял, что в sl находится строка, содержащая ожидаемок число, и ничего более кроме этого числа ?
← →
Slym © (2007-11-01 12:55) [14]Sergl (01.11.07 11:24) [12]
за тупость:)
Для особотупых повторяю: http://delphimaster.net/view/6-1192377094/
← →
Sergl © (2007-11-01 12:57) [15]
> Для особотупых повторяю
Попрошу без хамства... За ссылку спасибо.
← →
Sergl © (2007-11-01 13:04) [16]
> С чего ты взял, что в sl находится строка, содержащая ожидаемок
> число, и ничего более кроме этого числа ?
Я с сервера, перед отправкой файла, передаю вот это Socket.SendText(IntToStr(ms.Size) + #0);
Я так думаю что клиент следующим сообщением получает ms.Size
← →
Sergl © (2007-11-01 13:20) [17]Как, всетаки, дописать к моему потоку, перед отправкой, #end_file#.
Так ms.write(#end_file#,10) - что то не работает
← →
Sergl © (2007-11-01 13:22) [18]Ковычки забыл) - ms.write("#end_file#",10);
← →
Сергей М. © (2007-11-01 13:38) [19]
> клиент следующим сообщением получает ms.Size
>
Может получить, а может и не получить.
TCP - протокол поточный, а не месседж-ориентированный, в нем нет разбиения на сообщения, данные передаются сплошным потоком.
← →
Sergl © (2007-11-01 13:45) [20]Данные передаются партиями(я так понимаю), и что бы при передачи размера небыло лишнего сзади я ставлю #0. А чтобы небыло лишнего спереди я могу отсылать что-то вроде #start_file#
← →
Sergl © (2007-11-01 13:51) [21]Как, всетаки, дописать к моему потоку, перед отправкой, #end_file#.
Так ms.write(#end_file#,10) - что то не работает
← →
Сергей М. © (2007-11-01 13:57) [22]
> Данные передаются партиями(я так понимаю)
Неправильно понимаешь.
Данные передаются потоком.
← →
Slym © (2007-11-02 06:07) [23]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байт) причем каждый раз разного количества и размера :)
← →
Prostoy_paren (2007-11-06 12:57) [24]>Slym ©
Короче говоря тебе прийдется проверять сохранять все что тебе пришло в заранее подготовленном буфере(TMemoryStream подойдет)!
Потом анализировать на нахождение нуля #0 в твоем буфере.
Затем разбирать свой начало файла(его размер) и конец.
Тебе выше объясняли, что TCP может прислать от 1 и до MaxBuf байт.(MaxBuf=8192 байт - хотя это тоже можно настроить! :) ).
И вопрос нахрена тебе конец файла если ты посылаеш его длину?
И зачем посылать текстовую длину файла, если можно заполнить структуру скажем:
TFileRec=Record
FileStart:String[10];
FileSize :Cardinal;
...
End;
И проверять на наличие определенного(постоянного) размера данных в буфере приема?
А то работа со строками это всегда гемор (по моему мнению)
← →
Prostoy_paren (2007-11-06 13:26) [25]Т.е.
...
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;
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2008.10.12;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.08 c