Благодаря американской компьютеризированной системе выборов президента, тысячи российских хакеров смогли принять участие в голосовании...
// а форме ServerSocket1, ClientSocket1 : (Active := False,// Host := localhost, Port := 2001, xType := xNonBlocking),// OpenDialog1, Button1, Memo1.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;
ifnot 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;
beginrepeat
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;
Here's the translation of the content into Russian:
Проект Delphi!
Чтобы отправить файл с помощью не блокирующего сокета, вы на правильном пути. Вот разбивка того, что ваш код делает, и некоторые предложения для улучшения.
Серверная сторона
В Button1Click, когда кнопка кликается, загружается файл из OpenDialog и отправляется клиенту с помощью SendStreamThenDrop. Этот метод блокирующий, то есть сервер будет ждать, пока не будет отправлено все содержимое файла, прежде чем вернуться. Если вы хотите использовать не блокирующие сокеты, вам стоит рассмотреть использование асинхронного ввода-вывода или нескольких потоков.
Клиентская сторона
В OnConnect, вы создаете новый объект TFileStream и присваиваете ему переменной fStream. Это хорошая практика, потому что она обеспечивает закрытие файла при потере соединения.
В OnRead, вы получаете данные из сокета с помощью Socket.ReceiveBuf. Затем вы записываете эти данные в объект fStream. Если полученный счетчик больше 0, вы добавляете размер полученных данных в коллекцию строк Memo1. Это указывает на прогресс передачи файла.
Предложения
Чтобы улучшить ваш код и сделать его более эффективным:
Используйте асинхронный ввод-вывод: вместо блокировки при отправке или получении данных рассмотрите использование компонента TAsyncSocket Delphi, который обеспечивает асинхронную поддержку сокетов.
Используйте несколько потоков: вы можете создать отдельный поток для обработки передачи файла, освободив основной поток для выполнения других задач.
Реализуйте обработку ошибок: ваш код не обрабатывает ошибки должным образом. Например, если файл не может быть загружен или отправлен, ваш программ будет терминироваться внезапно.
Оптимизируйте размер буфера: константа MAX_BUF_SIZE установлена в 4095 байт, что может не быть оптимальным для всех систем. Рассмотрите использование более динамического подхода для определения оптимального размера буфера.
Вот пример, как вы можете модифицировать ваш код для использования асинхронного ввода-вывода с помощью TAsyncSocket:
Серверная сторона
procedureTfmMain.Button1Click(Sender:TObject);varsStream:TMemoryStream;beginsStream:=TMemoryStream.Create;ifnotOpenDialog1.ExecutethenExit;sStream.LoadFromFile(OpenDialog1.FileName);ServerSocket1.AsyncSendFile(sStream,'file transferred');end;procedureTfmMain.ServerSocket1AsyncSendFile(Sender:TObject;Stream:TStream);begin// Отправьте файл асинхронно с помощью метода SendFile компонента TAsyncSocketend;
Клиентская сторона
procedureTfmMain.ClientSocket1Connect(Sender:TObject;Socket:TCustomWinSocket);beginfStream:=TFileStream.Create('Receive.fil',fmCreate);end;procedureTfmMain.ClientSocket1Read(Sender:TObject;Socket:TCustomWinSocket);varcount:Integer;buffer:Array[0..MAX_BUF_SIZE]ofChar;beginrepeatSocket.Lock;count:=Socket.ReceiveBuf(buffer,SizeOf(buffer));ifcount>0thenfStream.WriteBuffer(buffer,count);Socket.Unlock;Memo1.Lines.Add(IntToStr(fStream.Size));until(count<=0);// Закройте файловый поток при завершении передачиfStream.Free;end;
Помните обрабатывать ошибки и исключения должным образом в вашем коде. Это только пример, чтобы дать вам идею о том, как использовать асинхронный ввод-вывод с помощью TAsyncSocket.
В статье описывается способ пересылки файлов через неблокирующий сокет (nonBlocking socket) в Delphi, используя компоненты ServerSocket и ClientSocket.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.