Краткое содержание статьи:
Delphi — это мощный инструмент. Написание программного обеспечения с помощью Delphi может значительно сократить цикл разработки программного обеспечения. В этой статье рассказывается, как использовать Delphi для написания программы двухточечной передачи файлов.
----------------------------------------------
Delphi — это мощный инструмент. Написание программного обеспечения с помощью Delphi может значительно сократить цикл разработки программного обеспечения. Основная идея передачи файлов «точка-точка» заключается в том, что серверное и клиентское программное обеспечение используют один и тот же порт. После подключения клиент отправляет на сервер запрос, включая имя файла, размер и т. д. файл для передачи. Если сервер примет и начнет передачу файлов. Конечно, есть два режима передачи файлов: ASCII-код и Bin, но в целом Bin достаточно. Основываясь на приведенном выше обсуждении, изначально это можно было сделать с помощью элементов управления Delphi4 NMStrm и NMStrmServ, но я протестировал это и обнаружил, что элемент управления NMStrm все еще можно использовать для файлов меньшего размера и это очень удобно, но если файл большой (1M) , произойдет ошибка. Итак, затем мы используем TServerSocket и TClientSocket в Delphi для написания этой программы. Из-за ограничения размера пакета Ethernet и механизма обработки DelphiSocket (в Delphi, когда вы используете Socket для отправки большего потока, получатель запускает OnRead несколько раз). . событие, Delphi гарантирует целостность каждых данных только в нескольких событиях OnRead, а не собирает сами данные и не возвращает их пользователю, поэтому не думайте, что вы можете отправить файл для передачи один раз в один Socket и Recv один раз в другом. Вам придется собирать данные самостоятельно или самостоятельно определять протокол), поэтому мы применяем метод специального протокола. Канонический способ определения протокола — использовать Record End. нравиться:
TMyFilePROtocol=Запись
sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...);
iДлина: целое число;
bufSend: Буфер;
Конец;
Я пробовал этот метод, но он не удался, и я всегда думал, что мой метод правильный, но программа всегда не компилировалась, я думаю, что-то не так с Delphi :) Поэтому в следующем примере программы я использовал другой метод. В классе Socket есть два свойства, ReceiveText и ReceiveBuf. В событии OnRead эти два свойства можно использовать только один раз, поэтому мы можем использовать глобальную переменную, чтобы сохранить, следует ли читать Text или Buf, то есть читать. Отправьте текст один раз и прочитайте его еще раз. Но это имитирует TMyFileProtocol.
Запустите программу:
Напишите самый простой вариант, в основном используемый для объяснения метода.
Определить протокол:
Конст
MP_QUERY = '1';
MP_REFUSE = '2';
MP_ACCEPT = '3';
MP_NEXTWILLBEDATA = '4';
MP_DATA = '5';
MP_ABORT = '6';
MP_OVER = '7';
MP_CHAT = '8';
Введение соглашения:
Сначала Клиент отправляет MP_QUERY, а после его получения Сервер отправляет MP_ACCEPT или MP_FEFUSE;
Клиент отправляет MP_FILEPROPERTY после получения MP_ACCEPT, а Сервер отправляет MP_NEXTWILLBEDATA после его получения;
Клиент отправляет MP_NEXTWILLBEDATA после его получения, а Сервер отправляет MP_DATA после его получения;
Клиент получает MP_DATA и отправляет данные, Сервер получает данные и отправляет MP_NEXTWILLBEDATA;
Цикл, пока Клиент не отправит MP_OVER;
MP_CHAT+String можно отправлять друг другу посередине;
Серверная программа:
Поместите следующие элементы управления: SaveDialog1, btnStartServer,
сс,(TServerSocket)
btnStartServer.OnClick(Отправитель:TObject);
начинать
сс.Порт:=2000;
сс.Открыть;
конец;
ss.OnClientRead(Отправитель: TObject;Socket: TCustomWinSocket);
вар
сТемп: строка;
bufRecv: Указатель;
iRecvLength: целое число;
начинать
если bReadText, то
начинать
sTemp:=Socket.ReceiveText;
случай sTemp[1] из
MP_QUERY:начать
//Отклонить здесь
SaveDialog1.FileName:=Copy(sTemp,2,Length(STemp));
если SaveDialog1.Execute, то
начинать
Socket.SendText(MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
конец
еще Socket.SendText(MP_REFUSE+'die');
конец;
MP_FILEPROPERTY:начать
//Чтобы отправить StrToInt(Copy(sTemp,2,Length(sTemp))) раз
//Отображение прогресса времени. . .
Socket.SendText(MP_NEXTWILLBEDATA);
конец;
MP_NEXTWILLBEDATA: начало
Socket.SendText(MP_DATA);
bReadText: = ложь;
конец;
MP_END:начать
fsRecv.Free
bReadText:=истина;
конец;
MP_ABORT:начать
fsRecv.Free;
bReadText:=истина;
конец;
MP_CHAT:начать
//Сообщение в чате
конец;
конец;{случай}
конец
еще начать
пытаться
GetMem(bufRecv,2000);//2000 должен >iBYTESEND
Socket.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
окончательно
FreeMem(bufRecv,2000);
конец; {попробовать}
bReadText:=истина;
Socket.SendText(MP_NEXTWILLBEDATA);
конец;
конец;
Клиентская программа:
Поместите следующие элементы управления: edtipAddress, OpenDialog1, btnConnect, btnSendFile,
cs (TClientSocket).
btnConnect.OnClick(Отправитель:TObject);
начинать
cs.Address:=edtIPAddress.Text;
cs.Порт:=2000;
cs.Соединиться;
конец;
btnSendFile.OnClick(Отправитель:TObject);
начинать
если OpenDialog1.Execute, то
Начинать
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);//FileSize???