Початківці програмісти (і я сам, коли починав вчити Delphi), задаються питанням: як же передати файл через сокети, якщо крім цього файлу через сокет передається ще купа інформації. Начебто проблема не така вже й складна, але все ж не з легких. Після довгих пошуків в інтернеті, я так і не знайшов жодної корисної статті по цій темі. Ось я і вирішив виправити цей недолік, і в цій статті я постараюся допомогти вирішити цю проблему.
Напишемо програму, яка зможе передавати файли через сокети (клієнт і сервер), і крім цього інші команди, наприклад яке-небудь повідомлення. Клієнт буде приймати файли або команди, а сервер - відсилати. Якщо ж клієнт буде все підряд записувати в буфер, то крім файлу, в ньому будуть і команди, а нам потрібно зробити так, щоб файли і команди не в якому разі не зливалися. Ще потрібно враховувати, що якщо файл великий, то при пересиланні, він розріже на кілька пакетів, тобто файл перешле не в одному пакеті, а в декількох, і подія OnClientRead буде викликатися кілька разів. В цьому і полягає основна проблема передачі!
Щоб можна було відокремити команди від файлу, спочатку пошлемо клієнту приблизно такий рядок: "file # file.txt # 16", тобто: команда + роздільник + ім'я файлу + роздільник + розмір файлу.
При отриманні даної команди, клієнт перейде в режим прийому файлу і все підряд буде записувати в буфер, до тих пір поки розмір файлу не буде дорівнює розміру прийнятих даних. Таким чином клієнт відокремить команди від файлу!
І так приступимо до написання коду:
Почнемо з сервера (він буде посилати файл):
Додайте на форму наступні компоненти: TServerSocket, TButton, TEdit, TProgressBar і TStatiusBar. Розмістіть їх як показано на малюнку.
Встановіть у компонента TServerSocket, порт (port): 1001 Отримати.
Встановіть у компонента TStatusBar, змінну SimplePanel в true.
В рядку. вводиться назва файлу для передачі, кнопка TButton, використовується для передачі файлу.
Спочатку додамо буфер для файлу в глобальні змінні:
Тепер зробимо, щоб при створенні форми, відкривався сокет:
При завершенні програми, потрібно не забути закрити сокет:
При натисканні на кнопку посилаємо файл:
На подію OnClientRead, компонента TServerSocket, впишіть наступний код:
Це потрібно для того, щоб сервер вбив буфер, тільки після того, як клієнт прийме файл. Якщо вбити буфер, відразу після передачі файлу, то клієнт не встигне прийняти весь файл. Як тільки клієнт прийме файл, він пошле сервера команду "end", що означає файл прийнятий, і сервер вб'є буфер.
Тепер зробимо щоб наш сервер виводив трохи інформації про з'єднання:
На подію OnClientConnect, компонента TServerSocket впишіть наступний код:
А на подію OnClientDisconnect впишіть:
Ось сервер і готовий. Тепер перейдемо до клієнта (він приймає файл) з пім метушні буде побільше:
Оголошуємо змінні і оду процедуру. Запишіть змінні саме в private. інакше нічого не буде працювати:
На подію створення форми, ми єднаємося з сервером і чекаємо передачі файлу:
При завершенні програми, закриваємо сокет:
Так-же як і у сервера, зробимо щоб клієнт видавав інформацію про з'єднання:
Тепер нам потрібно вписати код в процедуру Writing. Ця процедура потрібна для того, щоб прийняті дані записувати в файл. Код процедури:
Тепер на подію OnClientRead компонента TClientSocket, впишіть наступний код:
Таким чином, якщо файл великий, і подія OnClientRead буде викликатися жоден раз, а кілька, то якщо клієнт в режимі прийому файлу, він буде записувати дані в буфер, якщо ж ні, то клієнт визначить прийняту команду, і якщо це файл, то перейде в режим прийому файлу. Якщо ви чогось не зрозуміли, то прочитайте код програми, я там не дарма все раскоментіровал :-)
Ну от і все.
Клієнт і сервер - готові. Спочатку запустіть сервер, а за тим клієнта і спробуйте передати файли, розміром в декілька мегабайт :-) Я без проблем пересилав по мережі файли розміром 10-12 Мб.
Удачі в програмуванні!