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

Вниз

Не пойму где ошибка(сокеты)...   Найти похожие ветки 

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

Наверх




Память: 0.53 MB
Время: 0.017 c
15-1219085284
programmer90
2008-08-18 22:48
2008.10.12
Нужен инсталлятор


15-1219391037
brother
2008-08-22 11:43
2008.10.12
ручное обновление AviraAntivir


6-1193993911
Artik
2007-11-02 11:58
2008.10.12
Запуск программ по сети.


15-1219433767
{RASkov}
2008-08-22 23:36
2008.10.12
Математика


2-1220612113
Dagir
2008-09-05 14:55
2008.10.12
метод Locate