Регистрация Главная Сообщество
Сообщения за день Справка Регистрация
Навигация
Zhyk.org LIVE! Реклама на Zhyk.org Правила Форума Награды и достижения Доска "почета"

Ответ
 
Опции темы
Старый 12.03.2014, 13:42   #1
Читер-спонсор
 Пехотинец
Аватар для .Master.
 
.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза.Master. трижды герой Советского Союза
Регистрация: 21.07.2012
Сообщений: 95
Популярность: 6380
Сказал(а) спасибо: 631
Поблагодарили 460 раз(а) в 379 сообщениях
 
По умолчанию Для пересылки файлов через сокеты.

В этой теме я попробую доступно вам объяснить, как написать программу, которая сможет передавать файлы через сокеты (клиент и сервер), и кроме этого другие команды, например какое нибудь сообщение. Клиент у нас с вами будет принимать файлы или команды, а сервер - отсылать. Если наш клиент будет все подряд записывать в буфер, то кроме файла, в нём будут и команды, а нам нужно сделать так, чтоб файлы и команды не в коем случае не сливались. Так же мы должно учесть, если файл большой, то при пересылке, он разрежется на несколько пакетов, то есть файл перешлется не в одном пакете, а в нескольких, и событие OnClientRead будет вызываться несколько раз.

Чтобы мы смогли отделить команды от файла, сначала пошлём клиенту примерно такую строку: "file#file.txt#16", то есть: команда + разделитель + имя файла + разделитель + размер файла. При получении этой команды клиент перейдёт в режим приёма файла и всё подряд будет записывать в буфер, до тех пор пока размер файла не будет равен размеру принятых данных.


Начнем кодить...

Начнем с сервера, он будет посылать наш файл.

Кидаем на форму TServerSocket, TButton, TEdit, TProgressBar, TStatiusBar.

Устанавливаем у компонента TServerSocket, порт (port): 1001. У компонента TStatusBar, переменную SimplePanel в true. В строке, у нас вводится название файла для передачи, а кнопка ТБуттон - используется для передачи файла.


Сначала добавим буфер для файла в глобальные переменные:

Код:
.. var Form1: TForm1; 

MS: TMemoryStream; // Буфер для файла


Теперь сделаем, чтоб при создании формы, открывался сокет:


procedure TForm1.FormCreate(Sender: TObject); 

begin

ServerSocket1.Open; // Открываем сокет

end;
При завершении приложения, нужно не забыть закрыть сокет:

Код:
procedure TForm1.FormDestroy(Sender: TObject);

begin

ServerSocket1.Close; // Закрываем сокет 

end;
При нажатии на кнопку - посылаем файл:

Код:
procedure TForm1.Button1Click(Sender: TObject); // Передаём файл

var 

Size: integer; 

P: ^Byte;

begin

MS := TMemoryStream.Create; // Создаём буфер для файла 

MS.LoadFromFile(Edit1.Text); // Загружаем файл в буфер 

// Посылаем информацию о файл (команда # название # размер) 

ServerSocket1.Socket.Connections[0].SendText('file#'+Edit1.Text+'#'+IntToStr(MS.Size)+'#'); 

MS.Position := 0; // Переводим каретку в начало файла 

P := MS.Memory; // Загружаем в переменную "P" файл 

Size := ServerSocket1.Socket.Connections[0].SendBuf(P^, MS.Size); // Посылаем файл 

// Выводим прогресс 

ProgressBar1.Position := Size*100 div MS.Size; 

StatusBar1.SimpleText := 'Отправлено '+IntToStr(Size)+' из '+IntToStr(MS.Size)+' байт'

end;
В событии OnClientRead, компонента TServerSocket, впишите следующий код:

Код:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;

Socket: TCustomWinSocket);

begin

if Socket.ReceiveText = 'end' then // Если клиент принял файл, то...

begin

StatusBar1.SimpleText := 'Клиент принял файл';

MS.Free; // Убиваем буфер

end;

end;
Это нам нужно для того, чтобы сервер убил буфер, только после того, как клиент примет файл. Если убить буфер, сразу после передачи файла, то клиент не успеет принять весь файл. Как только клиент примет файл он пошлёт серверу команду "end", что значит файл принят, и сервер убьёт буфер.


Теперь попробуем сделать так, чтобы наш сервер выводил немного информации о соединении: На событие OnClientConnect, компонента TServerSocket впишите следующий код:

Код:
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;

Socket: TCustomWinSocket);

begin

StatusBar1.SimpleText := 'Соединение установлено';

end;
На событие OnClientDisconnect вписываем:

Код:
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;

Socket: TCustomWinSocket);

begin

StatusBar1.SimpleText := 'Соединение не установлено'; 

end;
Ок, сервер мы сделали. Давайте теперь перейдем к клиенту (он принимает файл) с ним как правило всегда больше возни.

Кидаем на форму: TClientSocket, две метки TLabel, TProgressBar и TStatusBar. У компонента TClientSocket устанавливаем порт (port): 1001 (как у сервера), а переменную адрес (address): 127.0.0.1 (ваш IP). Объявляем переменную и одну процедуру. Переменные записываем в private, иначе ничего у нас с вами не будет робить.


Код:
procedure Writing(Text: string); // Процедура записи в данных в буфер

private

{ Private declarations }

Name: string; // Имя файла

Size: integer; // Размер файла

Receive: boolean; // Режим клиента

MS: TMemoryStream; // Буфер для файла
На событие создания формы, мы соединяемся с сервером и ждём передачи файла:

Код:
procedure TForm1.FormCreate(Sender: TObject);

begin

ClientSocket1.Open; // Открываем сокет

Receive := false; // Режим клиента - приём команд

end;
По завершению приложения - закрываем сокет:

Код:
procedure TForm1.FormDestroy(Sender: TObject);

begin

ClientSocket1.Close; // Закрываем сокет

end;
Так же как и у сервера, делаем чтобы клиент выдавал информацию о соединении:

Код:
procedure TForm1.ClientSocket1Connect(Sender: TObject; 

Socket: TCustomWinSocket);

begin

StatusBar1.SimpleText := 'Соединение установлено';

end;


procedure TForm1.ClientSocket1Disconnect(Sender: TObject;

Socket: TCustomWinSocket);

begin

StatusBar1.SimpleText := 'Соединение не установлено';

end;
Теперь вписываем код в процедуру Writing. Процедура эта нужна нам для того, чтобы принятые данные записывать в файл. Код таков:

Код:
procedure TForm1.Writing(Text: string);

begin

if MS.Size < Size then // Если принято байт меньше размера файла, то...

MS.Write(Text[1], Length(Text)); // Записываем в буфер

// Выводим прогресс закачки файла

ProgressBar1.Position := MS.Size*100 div Size;

StatusBar1.SimpleText := 'Принято '+IntToStr(MS.Size)+' из '+IntToStr(Size);

if MS.Size = Size then // Если файл принят, то...

begin

Receive := false; // Переводим клиента в нормальный режим

MS.Position := 0; // Переводим каретку в начало буфера

MS.SaveToFile(Name); // Сохраняем файл

ClientSocket1.Socket.SendText('end'); // Посылаем команду "end", то есть файл принят

MS.Free; // Убиваем буфер

StatusBar1.SimpleText := 'Файл принят';

end; 

end;
Теперь на событие OnClientRead компонента TClientSocket, вписываем следующий код:

Код:
procedure TForm1.ClientSocket1Read(Sender: TObject;

Socket: TCustomWinSocket);

var

Rtext: string; // Принятый текст

begin

Rtext := Socket.ReceiveText;

if Receive then // Если клиент в режиме приёма файла, то...

Writing(RText) // Записываем данные в буфер

else // Если клиент не в режиме приёма файла, то...

if Copy(Rtext, 0, Pos('#', Rtext) -1) = 'file' then // Если это файл, то...

begin MS := TMemoryStream.Create; // Создаём буфер для файла

Delete(Rtext, 1, Pos('#', Rtext)); // Определяем имя файла

Name := Copy(Rtext, 0, Pos('#', Rtext) -1); // Определяем имя файла

Delete(Rtext, 1, Pos('#', Rtext)); // Определяем размер файла

Size := StrToInt(Copy(Rtext, 0, Pos('#', Rtext) -1)); // Определяем размер файла

Delete(Rtext, 1, Pos('#', Rtext)); // Удаляем последний разделитель

Label1.Caption := 'Размер файла: '+IntToStr(Size)+' байт'; // Выводим размер файла

Label2.Caption := 'Имя файла: '+Name; // Выводим имя файла

Receive := true; // Переводим сервер в режим приёма файла

Writing(RText); // Записываем данные в буфер

end;

end;
Если файл большой, и событие OnClientRead будет вызываться ни один раз, а несколько, то если клиент в режиме приёма файла, он будет записывать данные в буфер, если же нет, то клиент определит принятую команду, и если это файл, то перейдёт в режим приёма файла. Вот и все Клиент и сервер - готовы. Компилируем нашу программу и запускаем сервера, а потом клиенты.

Всем спасибо за внимание.
________________
[Ссылки могут видеть только зарегистрированные пользователи. ]
http://i.zhyk.ru/images/KM9hf.png
  Ответить с цитированием
Пользователь сказал cпасибо:
=F1= (12.03.2014)
Ответ


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[Помогите!] Сокеты gum_classis Вопросы и ответы, обсуждения 18 28.02.2012 20:37
[Баг] Баг на сокеты... viziir Читы, баги и статьи по WoW 9 18.08.2010 07:58
2.4.3 (ВС) сокеты и мета сокеты в любую шмотку!! -SHiSH- Читы, баги и статьи по WoW 0 26.04.2010 18:15

Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 01:10.

Пишите нам: [email protected]
Copyright © 2024 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net