Проги максимально простые, дабы не усложнять понимание.
Прога-клиент передает файл проге-серверу, а та пишет его на диск.
Окошко Port – порт TCP/IP – целое число от 1 до 65535
Окошко FileName – имя под которым файл будет записан на диск.
В окошке справа выбирается каталог куда нужно этот файл записать.
Сделав все как надо нажимаем кнопочку, кнопочка залипает и на ней загорается “Listen…” Сервер готов к приему файла.
На клиентской проге также выбираем пересылаемый файл кнопочкой SelectFile
Устанавливаем TCP/IP-порт и IP адрес сервера. Конектимся кнопкой Connect.
Кнопка Send становится доступной и мы легким движением руки отправляем файл.. Я отправлял файл-образ сидюка и он нормально перелился за несколько минут..
Код клиента прост:
Коннектимся:
procedure TfrmMain.bConnectClick(Sender: TObject);
begin
CS.Port:=strtoint(ePort.Text);
CS.Address:=eIP.Text;
CS.Active:=true;
end;
Где, CS – это ClientSocket
Сокет дает событие от том что коннект есть:
procedure TfrmMain.CSConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
l3.Caption:='Connect';
if OD.FileName<>'' then bSend.Enabled:=true;
end;
Мы этот радостный факт просто доводим до сведения юзера и если файл для пересылания выбран (OD – это OpenDialog), делаем кнопку “Send” доступной.
По нажатию “Send” отправляем файл на сервер:
procedure TfrmMain.bSendClick(Sender: TObject);
var fl:Longword;
begin
f:=TFileStream.Create(OD.FileName,fmOpenRead); {создаем поток-файл}
fl:=f.Size; {длину файла записываем в переменную fl}
CS.Socket.SendBuf(fl,SizeOf(fl)); {сначала отправим 4 байта в которых записана длина файла}
CS.Socket.SendStream(f); {все полился родимый}
{ SendStream(f) – автоматически грохает поток после отправки, так что нам больше с ним делать нечего }
end;
Вот и все на клиенте.
Переводим серверный сокет в состояние “Listen”
procedure TfrmMain.bListClick(Sender: TObject);
begin
if bList.Down then begin
SS.Port:=strtoint(EPort.Text);
SS.Active:=true;
bList.Caption:='Listen';end
else begin
SS.Active:=false;
bList.Caption:='Ready';
end;
end;
Кто-то к нам приконектился.. сообщим об этом и IP-шник напишем:
procedure TfrmMain.SSClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
lc.Caption:='Connected '+Socket.RemoteAddress;
end;
А вот и самое главное – событие OnClientRead, читаем данные и пишем их в файл..
procedure TfrmMain.SSClientRead(Sender: TObject; Socket: TCustomWinSocket);
var LengBuf { - длина буфера, байт}, PackByteCount:Longword; {- число байт в IP-пакете} Path:string; { - полный путь к файлу}
Buf:array[1..8192] of byte; { - собственно буфер для считываемых данных, логично было бы отъедать его функцией GetMem и такой длины какая указана в LengBuf, но я знаю что максимальная длина IP пакета 8192 байта..} ix:byte; PLong:^longword;
begin
ix:=1;
LengBuf:=Socket.ReceiveLength; {прочтем какой длины буфер требуется}
PackByteCount:=Socket.ReceiveBuf(Buf,LengBuf); {и считаем в Buf пришедший пакет}
if not assigned(f) then begin {если у нас нету никакого файла – так сделаем его}
PLong:=@Buf; {указатель PLong поставим на начало буфера}
FileLeng:=PLong^; {это нужно чтобы выловить первые 4 байта, там у нас длина файла как вы помните}
ix:=5; {а с 5-го байта пошли данные..}
Path:=DLB.Directory;
if Path[Length(Path)]<>'\' then Path:=Path+'\';
Path:=Path+EFileName.Text; {В Path – путь к файлу}
f:=TFileStream.Create(Path,fmCreate); {создаем поток-файл}
end;
f.Write(Buf[ix],PackByteCount-ix+1); {пишем данные..}
ByteCount:=ByteCount+PackByteCount;{считаем сколько байт записали}
lAcceptedByte.Caption:=inttostr(ByteCount); {отображаем эту информацию}
if ByteCount>=FileLeng+4 then {если все записали..}
begin
f.Free;f:=nil; {то грохнем поток нафиг..}
FileLeng:=0;ByteCount:=0;
end;
end;
Проще не бывает.