![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Не пойму где ошибка(сокеты)...
Sergl © (2007-11-01 10:05:00)Передаю файл через сокеты.
На сервере:
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#". Почему?
Prostoy_paren (2007-11-06 13:26:00) [1]Т.е.
...
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;
Prostoy_paren (2007-11-06 12:57:00) [2]>Slym ©
Короче говоря тебе прийдется проверять сохранять все что тебе пришло в заранее подготовленном буфере(TMemoryStream подойдет)!
Потом анализировать на нахождение нуля #0 в твоем буфере.
Затем разбирать свой начало файла(его размер) и конец.
Тебе выше объясняли, что TCP может прислать от 1 и до MaxBuf байт.(MaxBuf=8192 байт - хотя это тоже можно настроить! :) ).
И вопрос нахрена тебе конец файла если ты посылаеш его длину?
И зачем посылать текстовую длину файла, если можно заполнить структуру скажем:
TFileRec=Record
FileStart:String[10];
FileSize :Cardinal;
...
End;
И проверять на наличие определенного(постоянного) размера данных в буфере приема?
А то работа со строками это всегда гемор ( по моему мнению)
Slym (2007-11-02 06:07:00) [3]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байт) причем каждый раз разного количества и размера :)
Сергей М. (2007-11-01 13:57:00) [4]
> Данные передаются партиями(я так понимаю)
Неправильно понимаешь.
Данные передаются потоком.
Sergl (2007-11-01 13:51:00) [5]Как, всетаки, дописать к моему потоку, перед отправкой, #end_file#.
Так ms.write(#end_file#,10) - что то не работает
Sergl (2007-11-01 13:45:00) [6]Данные передаются партиями(я так понимаю), и что бы при передачи размера небыло лишнего сзади я ставлю #0. А чтобы небыло лишнего спереди я могу отсылать что-то вроде #start_file#
Сергей М. (2007-11-01 13:38:00) [7]
> клиент следующим сообщением получает ms.Size
>
Может получить, а может и не получить.
TCP - протокол поточный, а не месседж-ориентированный, в нем нет разбиения на сообщения, данные передаются сплошным потоком.
Sergl (2007-11-01 13:22:00) [8]Ковычки забыл) - ms.write('#end_file#',10);
Sergl (2007-11-01 13:20:00) [9]Как, всетаки, дописать к моему потоку, перед отправкой, #end_file#.
Так ms.write(#end_file#,10) - что то не работает
Sergl (2007-11-01 13:04:00) [10]
> С чего ты взял, что в sl находится строка, содержащая ожидаемок
> число, и ничего более кроме этого числа ?
Я с сервера, перед отправкой файла, передаю вот это Socket.SendText(IntToStr(ms.Size) + #0);
Я так думаю что клиент следующим сообщением получает ms.Size
Sergl (2007-11-01 12:57:00) [11]
> Для особотупых повторяю
Попрошу без хамства... За ссылку спасибо.
Slym (2007-11-01 12:55:00) [12]Sergl (01.11.07 11:24) [12]
за тупость:)
Для особотупых повторяю: http://www.delphimaster.ru/cgi-bin/forum.pl?id=1192377094&n=4
Сергей М. (2007-11-01 11:49:00) [13]
> DataSize:= StrToInt(sl);
С чего ты взял, что в sl находится строка, содержащая ожидаемок число, и ничего более кроме этого числа ?
Sergl (2007-11-01 11:24:00) [14]
> Write :)
Извеняюсь за тупость:)
Однако #end_file# так и не находит...
Сергей М. (2007-11-01 11:23:00) [15]
> Не хочет дописывать
А где ты дописываешь ? Нигде)
readпо-буржуйски - это читать, а не писать)
Slym (2007-11-01 11:22:00) [16]Sergl (01.11.07 11:21) [9]
Write :)
Sergl (2007-11-01 11:21:00) [17]Не хочет дописывать... ms.read('#end_file#',10);
Как дописать?
Slym (2007-11-01 11:13:00) [18]Sergl (01.11.07 11:10) [7]
Так пойдет?
Ходьбой это не назавешь... Похромает...
Sergl (2007-11-01 11:10:00) [19]Вместо socket.sendtext('#end_file#') дописать к ms, перед тем как отправить вот это ms.read('#end_file#',10);
Так пойдет?
Slym (2007-11-01 11:08:00) [20]Sergl (01.11.07 11:04) [4]
Подкинте пожалуйста литературу(ссылок) про работа с блокированием и не блокированием.
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1192377094&n=4