Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];

Вниз

Передача буфера большего чем ~270kb   Найти похожие ветки 

 
Nikolay   (2004-07-28 14:53) [0]

Уважаемые мастера!
Я понимаю, что вопрос о передаче файла через сокеты уже всех в корень задолбал, но вот никак не могу решить задачу. Буфер отсылается/принимается только если его размер сравнительно небольшой. Код клиента (отсылает):

// clt: TTcpClient; BlockMode = bmBlocking
procedure TFormClient.btnSendFileClick(Sender: TObject);
var
 data: TMemoryStream;
 s: String;
begin
 if dlgOpen.Execute then begin
   data := TMemoryStream.Create;
   data.LoadFromFile(dlgOpen.FileName);
   SetLength(s, data.Size);
   data.Position := 0;
   data.Read(s[1], data.Size);
   try
     if clt.Connect then begin
       clt.Sendln("file " + IntToStr(data.Size));
       clt.Disconnect;
       if clt.Connect then
         clt.SendBuf(s[1], Length(s);
     end;
   finally
     clt.Disconnect;
     data.Free;
   end;
 end;
end;


Сервер, принимающая сторона:

// srv: TTcpServer; BlockMode = bmThreadBlocking
procedure TFormServer.srvAccept(Sender: TObject;
 ClientSocket: TCustomIpClient);
var
 s: String;
 data: TMemoryStream;
begin
 if GetFile {индикатор приема} then begin
   data := TMemoryStream.Create;
   try
     SetLength(s, FileSize);
     // FileSize: integer; - узнается из строки "file XXXX"
     // посылаемой перед отправкой файла
     ClientSocket.ReceiveBuf(s[1], FileSize);
     data.Size := Length(s);
     data.Position := 0;
     data.Write(s[1], Length(s));
     data.SaveToFile("c:\test.tmp");
   finally
     data.Free;
     GetFile := False;
     FileSize := 0;
   end;
 end;
end;

На малых файлах работает. Большие не отправляются. Думаю загвоздка здесь (SendBuf() = -1):
-------
For non-blocking sockets, the data is sent to the WinSock DLL which has it"s own internal buffers. If the WinSock can accept additional data, SendBuf returns immediately with the number of bytes queued. If the WinSock internal buffer space is not able to accept the buffer being sent, SendBuf returns -1 and no data is queued at all. In this case, wait a bit for the WinSock to have a chance to send out already-queued data; then try again.
-------
Только как это обойти, я никак не могу понять... :(
Есть предложения?


 
Digitman ©   (2004-07-28 15:01) [1]


> Думаю загвоздка здесь (SendBuf() = -1):


... и далее цитируешьь справку для НЕблокирующего режима !
хотя ранее в своем коде явно отмечаешь , что у тебя блокирующий режим

// clt: TTcpClient; BlockMode = bmBlocking

чему верить ?


 
Nikolay   (2004-07-28 19:26) [2]

Упс, за замечание спасибо. Ну только тогда я вобще не въезжаю, почему SendBuf() возвращает -1 !?!

ps Верить тому, что сокеты работают в блок. режиме


 
Rouse_ ©   (2004-07-28 22:56) [3]

Это означает ошибку. Код ошибки смотри в WSAGetLastError


 
Nikolay   (2004-07-29 03:03) [4]

WSAECONNRESET
(10054)

Connection reset by peer.

A existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, or the remote host used a "hard close" (see setsockopt for more information on the SO_LINGER option on the remote socket.)
---------
Метод постоянно возвращает это значение! Пробовал убрать
clt.Disconnect
не помогло :(
По какой такой причине это происходит?


 
Slym ©   (2004-07-29 04:26) [5]

Херушки этот код будет работать....
ты че делаеш?...
Коннект
Отправляешь размер
ДИСКОННЕКТ!
Коннект
Отправляешь файл!
Глупо не правдя?


 
Slym ©   (2004-07-29 04:29) [6]

// clt: TTcpClient; BlockMode = bmBlocking
procedure TFormClient.btnSendFileClick(Sender: TObject);
var
data: TMemoryStream;
s: String;
begin
if dlgOpen.Execute then begin
  data := TMemoryStream.Create;
  data.LoadFromFile(dlgOpen.FileName);//это первая глупость! Зачем пямять под стреам и потом под строку?
  SetLength(s, data.Size);
  data.Position := 0;
  data.Read(s[1], data.Size);
  try
    if clt.Connect then begin
      clt.Sendln("file " + IntToStr(data.Size));
      clt.Disconnect;//вторая глупость...
      if clt.Connect then
        clt.SendBuf(s[1], Length(s);
    end;
  finally
    clt.Disconnect;
    data.Free;
  end;
end;
end;


 
Slym ©   (2004-07-29 04:48) [7]


procedure TFormClient.btnSendFileClick(Sender: TObject);
var
data: TFileStream;
begin
if dlgOpen.Execute then begin
 data := TFileStream.Create(dlgOpen.FileName,ReadOnly);
 try
   if clt.Connect then begin
     clt.Sendln("file " + IntToStr(data.Size));
     clt.SendStream(data);
   end;
 finally
   clt.Disconnect;
   data.Free;
 end;
end;


Сервер, принимающая сторона:


procedure TFormServer.srvAccept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
s: String;
data: TMemoryStream;
begin
if GetFile {индикатор приема} then begin
  data := TMemoryStream.Create;
  try
    s:=ClientSocket.Receiveln;
    delete(s,1,5);//удаляем file_
    data.Size := StrToInt(s);
    data.Position := 0;
    ClientSocket.ReceiveBuf(data.Memory^,data.Size,0);
    data.SaveToFile("c:\test.tmp");
  finally
    data.Free;
    GetFile := False;
    FileSize := 0;
  end;
end;
end;


 
Nikolay   (2004-07-29 07:35) [8]

Интересно, а этот код проверян? Специально создал отдельный проект. Скопировал все как здесь. Опять же, отсылает только часть файла! (или весь файл, если он маленький). Может есть рабочий исходник для пересылки файлов с использованием tcp?
В любом случае, спасибо!


 
Verg ©   (2004-07-29 08:16) [9]


> ClientSocket.ReceiveBuf(data.Memory^,data.Size,0);


И с чего вы взяли, что ReceiveBuf примет именно data.size байтов?
ReceiveBuf - это функция, возвращающая число реально принятых сокетом байтов.

procedure TFormServer.srvAccept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
s: String;
data: TFileStream;
Buffer : array[0..4095] of byte;
DataSize : integer;
Res : integer;

begin
if GetFile {индикатор приема} then begin
 data := TFileStream.Create("c:\test.tmp", fmCreate);
 try
   s:=ClientSocket.Receiveln;
   delete(s,1,5);//удаляем file_
   DataSize := StrToIntDef(s, 0);
   while DataSize > 0 do
   begin
      Res := ClientSocket.ReceiveBuf(Buffer, min(DataSize, sizeof(Buffer)), 0);
      // ф-ция min - модуль math
      if Res < 0 then
        raise Exception.Create(SysErrorMessage(WSAGetLastError)); // Ошибка
      if Res = 0 then
        break; // Неожиданный разрыв соединения
      Dec(DataSize, Res);
      Data.Write(Buffer, Res);
    end;
 finally
   data.Free;
   GetFile := False;
   FileSize := 0;
 end;
end;

end;


 
Nikolay   (2004-07-29 10:03) [10]

Другое дело!
Большое спасибо, вроде разобрался!


 
Digitman ©   (2004-07-29 10:10) [11]


> Verg ©   (29.07.04 08:16) [9]


а что, у TTcpServer нет события OnRead ? я просто не в курсе .. смотрю, ты в OnAccept все это хоз-во разместил, что в общем случае не есть корректно ... все-таки прием следует инициировать по факту FD_READ, а не FD_ACCEPT ...


 
Verg ©   (2004-07-29 10:17) [12]


> [11] Digitman ©   (29.07.04 10:10)


Серверная компонента TTCPServer - это многопоточный серевер, обслуживающий входящие соединения блокирующими сокетами. Каждому соединению - отдельный поток. Кроме того, будучи linux - совместимым, он про FD_*** знать ничего не должен.


 
Digitman ©   (2004-07-29 10:24) [13]


> Verg ©   (29.07.04 10:17) [12]


теперь все ясно, буду в курсе, спасибо



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.038 c
6-1091011983
Nikolay
2004-07-28 14:53
2004.10.03
Передача буфера большего чем ~270kb


4-1093715324
Valdemar
2004-08-28 21:48
2004.10.03
Защита CD от копирования


14-1094763527
Palladin
2004-09-10 00:58
2004.10.03
Посоветуйте смартфон...


3-1094126032
V l a d i m i r
2004-09-02 15:53
2004.10.03
Запрос SQL


8-1089744445
Mangust
2004-07-13 22:47
2004.10.03
PlaySound





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский