Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.11.2015, 22:21   #1
rachina
Пользователь
 
Регистрация: 15.03.2015
Сообщений: 27
По умолчанию отправка файлов через non blocking socket

доброго времени суток. пытаюсь реализовать отправку файлов через nonblocking socket
в справке по делфи нашёл код(представлен чуть ниже) и попытался модернизировать свой, но вылетает с ошибкой(((
raised exception class EListError with message 'List index out of bounds(0)

Код:
procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
    fStream:= TFileStream.Create('Receive.fil', fmCreate);
     Button1.Caption:= 'Отключить';
     Memo1.lines.Add('Сервер '+ClientSocket1.Host+' подключен.');
     ClientSocket1.Socket.SendText('USER ' + LabeledEdit1.Text + #13#10);            
     Memo1.Lines.Add('Client:   ' + 'USER ' + LabeledEdit1.Text);
     ClientSocket1.Socket.SendText('PASS ' + LabeledEdit2.Text + #13#10);
     Memo1.Lines.Add('Client:   ' + 'PASS ' + LabeledEdit2.Text);
end;
 
 
procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Button1.Caption:= 'Подключиться';
  Memo1.Lines.Add('Сервер '+ClientSocket1.Host+' отключен.');
  fStream.Free;
end;
 
 
procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  servmes: string;
    count :Integer;
  buffer: Array [1..MAX_BUF_SIZE] of Char;
begin
  servmes:= ClientSocket1.Socket.ReceiveText;
  servmes:= Trim(servmes);
  Memo1.Lines.Add('Server:  ' + servmes);
   repeat
    Socket.Lock;
    count:= Socket.ReceiveBuf(buffer,SizeOf(buffer));
    if count > 0 then
      fStream.WriteBuffer(buffer,count);
    Socket.Unlock;
   until (count <= 0);
 
   Memo1.Lines.Add(IntToStr(fStream.Size));
end;
 
 
procedure TForm1.Button1Click(Sender: TObject);
begin
 
   if not ClientSocket1.Active then begin
     ClientSocket1.Host:= LabeledEdit3.Text;
     ClientSocket1.Port:= StrToInt(LabeledEdit4.Text);
     ClientSocket1.Open;
     end else
     ClientSocket1.Close;
end;
 
    //Memo1.Lines.Add('Client:   ' + Edit1.Text);
 
 
procedure TForm1.Button3Click(Sender: TObject);
begin
     ClientSocket1.Socket.SendText('TYPE I' + #13#10);     //настройка
     ClientSocket1.Socket.SendText('SYST' + #13#10);
     ClientSocket1.Socket.SendText('CWD /' + #13#10);
     ClientSocket1.Socket.SendText('TYPE A' + #13#10);
     ClientSocket1.Socket.SendText('PWD' + #13#10);
     ServerSocket1.Open;
     ClientSocket1.Socket.SendText('PORT 127,0,0,1,194,50' + #13#10);  
     ClientSocket1.Socket.SendText('LIST' + #13#10);  
end;
 
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
    Memo1.Lines.Add('Есть контакт');
end;
 
 
procedure TForm1.StrokoDel(str: string);
var buf_str: string;
begin
while Length(str)>0 do
  begin
   if Pos(#13#10, str)>0 then
    begin
     buf_str:= Copy(str, 1, Pos(#13#10, str)-1);
     Delete(str, 1, Pos(#13#10, str)+1);
    end
   else buf_str:= str;
   ListBox1.Items.Add(buf_str);
  end;
end;
 
 
procedure TForm1.ServerSocket1ThreadStart(Sender: TObject;
  Thread: TServerClientThread);
  const  filename='qqq.txt';
  var {FileStream: TFileStream;}   dir_str: string;
begin
  Memo1.Lines.Add('что-то передаётся поток');
    {Открываем файл filename}
    //FileStream:= TFileStream.Create(filename,fmOpenRead);
    {Посылаем его первому подключенному клиенту}
    dir_str:= ServerSocket1.Socket.Connections[0].ReceiveText;     //Connections[0].SendStream(FileStream);
    //ListBox1.Items.Add(inttostr(pos('23', dir_str)+3));          //с 53 начинается имя файла
    StrokoDel(dir_str);
    {Закрываем файл}
    //FileStream.Free;
end;
 
procedure TForm1.ListBox1DblClick(Sender: TObject);
var filename: string;
begin
  filename:= Copy(ListBox1.Items[ListBox1.ItemIndex], 53, Length(ListBox1.Items[ListBox1.ItemIndex]));
  ListBox1.Items.Add(filename);
  //ClientSocket1.Socket.SendText('RETR' +  + #13#10);
end;
 
procedure TForm1.ServerSocket1ThreadEnd(Sender: TObject;
  Thread: TServerClientThread);
begin
ServerSocket1.Close;
end;
 
procedure TForm1.Button2Click(Sender: TObject);
var
  sStream : TMemoryStream;
begin
sStream := TMemoryStream.Create;
  if not OpenDialog1.Execute then
    Exit else
  sStream.LoadFromFile(OpenDialog1.FileName);
  ServerSocket1.Socket.Connections[0].SendStreamThenDrop(sStream);
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
 ServerSocket1.Active:=true;
  ClientSocket1.Active:=true;
end;

трассировка не очень помогает...
где допустил косяк? подскажите, пожалуйста!
по ходу, не видит он, что соединение активно
rachina вне форума Ответить с цитированием
Старый 21.11.2015, 22:22   #2
rachina
Пользователь
 
Регистрация: 15.03.2015
Сообщений: 27
По умолчанию

тут код из справки

Код:
procedure tfmmain.formcreate(sender: tobject);
begin
serversocket1.active:=true;
clientsocket1.active:=true;
end;
 
{--- server ---}
 
procedure tfmmain.button1click(sender: tobject);
var
sstream : tmemorystream;
begin
sstream := tmemorystream.create;
if not opendialog1.execute then
exit;
sstream.loadfromfile(opendialog1.filename);
serversocket1.socket.connections[0].sendstreamthendrop(sstream);
end;
 
{--- client ---}
 
const
max_buf_size = $4095;
 
var
fstream: tfilestream;
 
{onconnect}
procedure tfmmain.clientsocket1connect(sender: tobject;
socket: tcustomwinsocket);
begin
fstream:= tfilestream.create('receive.fil', fmcreate);
end;
 
{onread}
procedure tfmmain.clientsocket1read(sender: tobject;
socket: tcustomwinsocket);
var
count :integer;
buffer: array [0..max_buf_size] of char;
begin
repeat
socket.lock;
count:= socket.receivebuf(buffer,sizeof(buffer));
if count > 0 then
fstream.writebuffer(buffer,count);
socket.unlock;
until (count <= 0);
 
memo1.lines.add(inttostr(fstream.size));
end;
 
{ondisconnect}
procedure tfmmain.clientsocket1disconnect(sender: tobject;
socket: tcustomwinsocket);
begin
fstream.free;
end;
стопорится на строке
Код:
ServerSocket1.Socket.Connections[0].SendStreamThenDrop(sStream);
rachina вне форума Ответить с цитированием
Старый 21.11.2015, 22:45   #3
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
стопорится на строке
Если с ошибкой List index out of bounds(0), то проблема в том что нет подключения к серверу. Всмысле не то, чтоб клиент не подключался, а что именно при работе button1click подключение уже разорвано.
Цитата:
отправка файлов через non blocking socket
А можно поинтересоваться, почему не FTP? Почему не INDY или хотя бы WinInet?
Почему именно классика Делфи - старенькие сокеты?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 21.11.2015, 23:25   #4
rachina
Пользователь
 
Регистрация: 15.03.2015
Сообщений: 27
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Если с ошибкой List index out of bounds(0), то проблема в том что нет подключения к серверу. Всмысле не то, чтоб клиент не подключался, а что именно при работе button1click подключение уже разорвано.

А можно поинтересоваться, почему не FTP? Почему не INDY или хотя бы WinInet?
Почему именно классика Делфи - старенькие сокеты?
здравствуйте!
нужно реализовать протокол ftp, дабы понять принцип работы, вручную. использование инди облегчает работу))
rachina вне форума Ответить с цитированием
Старый 22.11.2015, 00:02   #5
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
дабы понять принцип работы
Здорово. А теория тебе известна?
Т.е. как именно протокол работает.
Например я четто тут не вижу открытия порта данных... Может плохо смотрю?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.11.2015, 00:42   #6
rachina
Пользователь
 
Регистрация: 15.03.2015
Сообщений: 27
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Здорово. А теория тебе известна?
Т.е. как именно протокол работает.
Например я четто тут не вижу открытия порта данных... Может плохо смотрю?
известно, конечно.
я тут кое-что подсократил, дабы влезло сюда


Код:
var
  Form1: TForm1;
  fStream: TFileStream;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
    fStream:= TFileStream.Create('Receive.fil', fmCreate);
     Button1.Caption:= 'Отключить';
     Memo1.lines.Add('Сервер '+ClientSocket1.Host+' подключен.');
     ClientSocket1.Socket.SendText('USER ' + LabeledEdit1.Text + #13#10);            
     Memo1.Lines.Add('Client:   ' + 'USER ' + LabeledEdit1.Text);
     ClientSocket1.Socket.SendText('PASS ' + LabeledEdit2.Text + #13#10);            
     Memo1.Lines.Add('Client:   ' + 'PASS ' + LabeledEdit2.Text);
end;


procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Button1.Caption:= 'Подключиться';
  Memo1.Lines.Add('Сервер '+ClientSocket1.Host+' отключен.');
  fStream.Free;
end;


procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  servmes: string;
    count :Integer;
  buffer: Array [1..MAX_BUF_SIZE] of Char;
begin
  servmes:= ClientSocket1.Socket.ReceiveText;
  servmes:= Trim(servmes);
  Memo1.Lines.Add('Server:  ' + servmes);
   repeat
  Socket.Lock;
    count:= Socket.ReceiveBuf(buffer,SizeOf(buffer));
    if count > 0 then
      fStream.WriteBuffer(buffer,count);
    Socket.Unlock;
   until (count <= 0);
   Memo1.Lines.Add(IntToStr(fStream.Size));
end;


procedure TForm1.Button1Click(Sender: TObject);
begin

   if not ClientSocket1.Active then begin
     ClientSocket1.Host:= LabeledEdit3.Text;
     ClientSocket1.Port:= StrToInt(LabeledEdit4.Text);
     ClientSocket1.Open;
     end else
     ClientSocket1.Close;
end;



procedure TForm1.Button3Click(Sender: TObject);
begin
     ClientSocket1.Socket.SendText('TYPE I' + #13#10);     
     ClientSocket1.Socket.SendText('SYST' + #13#10);
     ClientSocket1.Socket.SendText('CWD /' + #13#10);
     ClientSocket1.Socket.SendText('TYPE A' + #13#10);
     ClientSocket1.Socket.SendText('PWD' + #13#10);
     ServerSocket1.Open;                                  //открыть сокет для потока
     ClientSocket1.Socket.SendText('PORT 127,0,0,1,194,50' + #13#10);   //  49714
     ClientSocket1.Socket.SendText('LIST' + #13#10);   //лист директории

     //ClientSocket1.Socket.SendText('LIST' + #13#10);
     //ClientSocket1.Socket.SendText('CWD /' + #13#10);
     //ClientSocket1.Socket.SendText('MKD qwerty' + #13#10);     //создание директории
     //ClientSocket1.Socket.SendText('PASV' + #13#10);

     //ClientSocket1.Socket.SendText('RETR qqq.txt' + #13#10);
end;

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
    Memo1.Lines.Add('Есть контакт');
end;


procedure TForm1.StrokoDel(str: string);
var buf_str: string;
begin
while Length(str)>0 do
  begin
   if Pos(#13#10, str)>0 then
    begin
     buf_str:= Copy(str, 1, Pos(#13#10, str)-1);
     Delete(str, 1, Pos(#13#10, str)+1);
    end
   else buf_str:= str;
   ListBox1.Items.Add(buf_str);
  end;
end;


procedure TForm1.ServerSocket1ThreadStart(Sender: TObject;
  Thread: TServerClientThread);
  const  filename='qqq.txt';
  var {FileStream: TFileStream;}   dir_str: string;
begin
  Memo1.Lines.Add('что-то передаётся поток');
    {Открываем файл filename}
    //FileStream:= TFileStream.Create(filename,fmOpenRead);
    {Посылаем его первому подключенному клиенту}
    dir_str:= ServerSocket1.Socket.Connections[0].ReceiveText;     //Connections[0].SendStream(FileStream);
    //ListBox1.Items.Add(inttostr(pos('23', dir_str)+3));          //с 53 начинается имя файла
    StrokoDel(dir_str);
    {Закрываем файл}
    //FileStream.Free;
end;

procedure TForm1.ListBox1DblClick(Sender: TObject);
var filename: string;
begin
  filename:= Copy(ListBox1.Items[ListBox1.ItemIndex], 53, Length(ListBox1.Items[ListBox1.ItemIndex]));
  ListBox1.Items.Add(filename);
  //ClientSocket1.Socket.SendText('RETR' +  + #13#10);
end;

procedure TForm1.ServerSocket1ThreadEnd(Sender: TObject;
  Thread: TServerClientThread);
begin
ServerSocket1.Close;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  sStream : TMemoryStream;
  i: integer;
begin
sStream := TMemoryStream.Create;
//if serversocket1.Socket.ActiveConnections=1 then begin
  if not OpenDialog1.Execute then
    Exit else
  sStream.LoadFromFile(OpenDialog1.FileName);
  ServerSocket1.Socket.Connections[0].SendStreamThenDrop(sStream);    //  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 ServerSocket1.Active:=true;
  ClientSocket1.Active:=true;
end;

end.

что-то похожее на то, что вы говорите есть?
я тут экспериментировал как мог...

Последний раз редактировалось rachina; 22.11.2015 в 01:22.
rachina вне форума Ответить с цитированием
Старый 22.11.2015, 00:43   #7
rachina
Пользователь
 
Регистрация: 15.03.2015
Сообщений: 27
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Может плохо смотрю?
Код:
ServerSocket1.Open;
а клиенту открываю сокет при подключении
rachina вне форума Ответить с цитированием
Старый 22.11.2015, 01:53   #8
rachina
Пользователь
 
Регистрация: 15.03.2015
Сообщений: 27
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Например я четто тут не вижу открытия порта данных...
вы действительно оказались правы.

Код:
procedure TForm1.Button2Click(Sender: TObject);
var
  sStream : TMemoryStream;
  i: integer;
begin
if serversocket1.Active=false then begin edit1.text:='не работаю'; end;
sStream := TMemoryStream.Create;
if not OpenDialog1.Execute then
    Exit;
ServerSocket1.onclientread;
  sStream.LoadFromFile(OpenDialog1.FileName);
  ServerSocket1.Socket.Connections[0].SendStreamThenDrop(sStream);
end;
но как тогда быть? о0 как открыть этот порт данных?
rachina вне форума Ответить с цитированием
Старый 22.11.2015, 10:26   #9
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Ух... На пальцах то так и не расскажешь...
Теория тебе нужна, причем знать ее нужно на зубок.
FTP использует два порта. Первый порт - порт команд. Клиент отсылает серверу строку, которую он распознает как имя команды. Это у тебя есть:
Код:
ClientSocket1.Socket.SendText('LIST' + #13#10);   //лист директории
Однако ответ от сервера на эту команду не всегда приходит в тот же порт в то же подключение.
Нужен второй порт, который будет открыт для считывания результата данных, а после закрыт. Он используется такими командами как LIST, RETR, STOR. Именно за счет этого ФТП и умеет передавать данные огромных размеров не путая данные с командами. Мухи от котлет отдельно короче. Схема примерно такая:
1) Открывается порт
2) Посылается команда
3) Клиент ждет ответ на команду попутно считывая данные из второго канала
4) Когда ответ на команду от сервера по каналу команд будет получен, второй канал закрывается, считая что команда выполнена и ответ на нее из второго канала передан.

Однако есть два режима открытия второго канала - пассивный и активный. И вот от них уже зависит, как и кто будет открывать порт и какой именно.
Посмотри, у тебя есть такая строка:
Код:
ClientSocket1.Socket.SendText('PORT 127,0,0,1,194,50' + #13#10);   //  49714
Скажи, ты знаешь что она приказывает серверу сделать?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.11.2015, 16:08   #10
rachina
Пользователь
 
Регистрация: 15.03.2015
Сообщений: 27
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Посмотри, у тебя есть такая строка:
Код:
ClientSocket1.Socket.SendText('PORT 127,0,0,1,194,50' + #13#10);   //  49714
Скажи, ты знаешь что она приказывает серверу сделать?
думаю, да. это активный режим. команда указывает серверу адрес и порт, которые будут использоваться клиентом для прослушивания соединения

Цитата:
Сообщение от Stilet Посмотреть сообщение
Однако есть два режима открытия второго канала - пассивный и активный.[/CODE]
Скажи, ты знаешь что она приказывает серверу сделать?
ещё вычитал, что данные принимать/отправлять надо в пассивном режиме. в принципе, смог перейти в этот режим без проблем.
отправил серверу PASV, на что он ответил мне положительно.
но до меня что-то пока не доходит всё равно

Последний раз редактировалось Stilet; 22.11.2015 в 17:57.
rachina вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Delphi 7 ClienSocket.Socket.SendText(Edt2), отправка текста на сервер с заданным шрифтом.. Aristocrat Работа с сетью в Delphi 1 25.10.2014 10:36
ip через socket xil C# (си шарп) 2 28.07.2011 19:14
Получение и отправка личных сообщений в чате через Socket darek13 Работа с сетью в Delphi 9 12.06.2011 06:13
Отправка файлов через smtp BoT_T Работа с сетью в Delphi 0 24.09.2010 11:53
Отправка файлов по условию через Outlook 2003 Freerider1972 Microsoft Office Excel 3 27.07.2010 15:27