|  | 
 
 | 
| 
 | |||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны | 
|  | 
|  | Опции темы | Поиск в этой теме | Опции просмотра | 
| 
			 
			#1  
			
			
			
			
		 | |||
| 
 | |||
|  Передача файлов через TcpServer/TcpClient Всем привет! Пытаюсь передать файл с клиента на сервер: Сервер: Код: var	
  stream: TMemoryStream;
  msg: string;
  sz: integer;
begin
  if ClientSocket.Connect then
  begin
    msg := ClientSocket.Receiveln;
    stream := TMemoryStream.Create;
    sz := StrToInt(msg);
    stream.SetSize(sz);
    ClientSocket.Sendln('ok');
    
    ClientSocket.ReceiveBuf(stream, sz);
    stream.SaveToFile(t[1]);
    stream.Free;
    t.Free;
    ClientSocket.Disconnect;
  end;
end;Клиент: Код: var
  stream: TMemoryStream;
  msg: string;
begin  
  if TcpClient1.Connect then
  begin    
    stream := TMemoryStream.Create;
    stream.LoadFromFile(source_file);
    TcpClient1.Sendln(IntToStr(stream.Size));
    if TcpClient1.Receiveln = 'ok' then
      TcpClient1.SendBuf(stream, stream.Size);
    TcpClient1.Disconnect;  
  end;
end;Файл передается, но при открытии пишет что поврежден. Размер файлов совпадает. В чем может быть проблема? | 
| 
			 
			#2  
			
			
			
			
		 | ||||
| 
 | ||||
|   Со Stream почти не работал, но попробуй сделать когда получаешь буффер ClientSocket.ReceiveBuf(stream.memory, sz); или как-то так | 
| 
			 
			#3  
			
			
			
			
		 | |||
| 
 | |||
|   неа, тоже самое( | 
| 
			 
			#4  
			
			
			
			
		 | ||||
| 
 | ||||
|   скажи пожалста 1) по какому событию в TCPServer работаешь 2) свойства сервера (в object inspector) | 
| 
			 
			#5  
			
			
			
			
		 | |||
| 
 | |||
|   1. OnAccept 2. BlockMode bmThreadBlocking LocalHost 127.0.0.1 LocalPort 8888 | 
| 
			 
			#6  
			
			
			
			
		 | ||||
| 
 | ||||
|   Итак. Сервер: Код: procedure TForm3.TcpServer1Accept(Sender: TObject;
  ClientSocket: TCustomIpClient);
var
  stream: TMemoryStream;
  msg: string;
  sz: integer;
begin
  if ClientSocket.Connect then
  begin
    msg := ClientSocket.Receiveln;
    stream := TMemoryStream.Create;
    sz := StrToInt(msg);
    stream.SetSize(sz);
    ClientSocket.Sendln('ok');
    ClientSocket.ReceiveBuf(stream.Memory^, sz);
    stream.SaveToFile('123.exe');
    stream.Free;
    ClientSocket.Disconnect;
  end;
end;Клиент: Код: procedure TForm4.Button1Click(Sender: TObject);
var
  stream: TMemoryStream;
  msg: string;
begin
  if TcpClient1.Connect then
  begin
    stream := TMemoryStream.Create;
    stream.LoadFromFile('C:\123.exe');
    TcpClient1.Sendln(IntToStr(stream.Size));
    if TcpClient1.Receiveln = 'ok' then
      TcpClient1.SendBuf(stream.Memory^, stream.Size);
    TcpClient1.Disconnect;
  end
  else showmessage('Error connecting');
end;У меня такой вариант работает. Дело в том, что recieveBuf(stream,X) по идеи некорректная запись: Stream - это по сути указатель. В итоге получается, что отправляется и принимается не то, что нужно, а X байт, начиная с адреса Stream в памяти. | 
| 
			 
			#7  
			
			
			
			
		 | |||
| 
 | |||
|   спасибо огромное, всё работает! забыл и в клиенте тоже указать stream.Memory^   | 
| 
			 
			#8  
			
			
			
			
		 | ||||
| 
 | ||||
|   Бывает) Да я сам тоже вначале забыл :-) | 
| 
			 
			#9  
			
			
			
			
		 | ||||
| 
 | ||||
|   Доброго времени суток ! А почему я не могу передать файлы более ~55Мб по вышеизложенному алгоритму ? Т.е. все передается, но если файл более ~55мБ, то он по прибытию получается "битым", причем его размер правильный. С Уважением. | 
| 
			 
			#10  
			
			
			
			
		 | ||||
| 
 | ||||
|   Передача больших файлов всегда вызывает небольшие проблемы. Не знаю уж, как реализованы TCP/IP компоненты в делфе, но когда я писал свои ради интереса, буфер размером больше 8 кб за раз не передавался вообще. Самое простое в данном случае решение на мой взгляд - отправлять файл по частям. То есть не сразу читаем весь файл в 100 МБ в память и шлем, а, например, читаем первые 10 МБ, отправляем, ждем подтвеждения, следующие 10 МБ, ... А можно и кусочки поменьше. | 
| 
			 
			#11  
			
			
			
			
		 | |||
| 
 | |||
|   Цитата: 
 В данном случае причин может быть 2: 1. Если установлен NonBlockingMode, дисконнект происходит до того как данные успеют уйти серверу. 2. Буфер передается драйверу, а у него память не резиновая - поэтому передавать за один раз такой несуразно большой буфер он может и отказаться, о чем сообщит ошибкой. Вы событие TCPClient.OnError обрабатываете? (WSA_NOT_ENOUGH_MEMORY = 8 Insufficient memory available. An application used a Windows Sockets function that directly maps to a Windows function. The Windows function is indicating a lack of required memory resources. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.) И еще у вас молоко убежало - в процедуре клиента stream не уничтожается. Последний раз редактировалось Lucky192, 05.10.2011 в 08:25. |