Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

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


Страницы:   1 2

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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо