![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа с памятью [D7, WinXP]
denkop © (2004-10-02 02:11:00)Возникла простая задача. Нужно в переменную типа Pointer поместить данные из пременной типа String.
Делаю так:
var
Buf:pointer;
St:string;
begin
St:='SendingFile';
GetMem(Buf,Length(St));
try
Move(St, Buf^, Length(St));
ShowMessage(IntToStr(SizeOf(Buf))); //здесь 4 вместо 11
ShowMessage(String(Buf^)); // здесь всё нормально
UDPClient.SendBuffer(Buf^, Length(St));
finally
FreeMem(Buf);
end;
end;
Но на сервер моя строка не доходит...
А вот этот кусок работает
var
Buf:pointer;
St:integer;
begin
St:=1111;
GetMem(Buf,SizeOf(St));
try
Move(St, Buf^, SizeOf(St));
ShowMessage(IntToStr(SizeOf(Buf))); // здесь всё нормально=4
ShowMessage(IntToStr(Integer(Buf^))); // здесь тоже
UDPClient.SendBuffer(Buf^, SizeOf(St));
finally
FreeMem(Buf);
end;
end;
т.е. проблема именно в помещении строки в буфер.
Подскажите пожалста, что я делаю не так.
kaZaNoVa (2004-10-04 18:35:00) [1]denkop © (02.10.04 11:37) [10]
> Хочу припаять функцию передачи файлов. Всегда было
> интересно, что у начальника на компе :))
Гы, это уже функции " трояна" - имхо нет гарантии, что начальник окажется так глуп, как ты предполагаешь .. - см [12]
Anatoly Podgoretsky (2004-10-03 09:53:00) [2]denkop © (02.10.04 11:37) [10]
А начальнику интересно подписывать заявление об твоем увольнение.
Германн (2004-10-03 03:17:00) [3]2 denkop © (02.10.04 11:31) [9]
Воскресенье. Голова уже работает в режиме "Выходных". Так что, если, то извини.
>Германн >>
>а если строка объявлена как string[...], тогда как
Если строка объявлена как string[...], то и St St[1]
denkop (2004-10-02 11:37:00) [4]Немного внесу ясности. Это маленький UDP чат и он уже работает и довольно успешно. Хочу припаять функцию передачи файлов. Всегда было интересно, что у начальника на компе :))
denkop (2004-10-02 11:31:00) [5]Германн >>
а если строка объявлена как string[...], тогда как
Defunct >> правильно, в коде этого ещё нет, но будет. если я отправлю как строку или с помощью udp.send(), а на сервере прочитаю аналогичным образом, а сервер ещё не знает, передаю я данные или команду, след-но данные могут исковеркаться. Жто всё для того, что бы незаморачиваться на сервере со всякими флагами (идёт передача или это только команда). Короче вот что получилось:
procedure TUDPMainForm.Button1Click(Sender: TObject);
var
ReceivedString: String;
FS1, FS2:TFileStream;
BytesRead, StartBit:integer;
AppDir, StartChr, St: String;
Buf:pointer;
const
BufSize=1024*8;
begin
StartChr:='SendFile';
AppDir:=ExtractFilePath(Application.ExeName);
FS1:=TFileStream.Create(AppDir+'1.exe', fmOpenRead);
GetMem(Buf,BufSize);
try
St:=StartChr+'=222.exe';
Move(St[1],Buf^,Length(St));
UDPClient.SendBuffer(Buf^, Length(St));
repeat
BytesRead:=FS1.Read(Buf^,BufSize);
UDPClient.SendBuffer(Buf^,BytesRead);
ReceivedString := UDPClient.ReceiveString();
if ReceivedString = '' then
begin ShowMessage('No answer '+IntToStr(BytesRead)); Exit; end;
Application.ProcessMessages;
until BytesRead=0;
finally
FS1.Free;
FS2.Free;
FreeMem(Buf);
end;
ShowMessage('Complete');
end;
procedure TUDPMainForm.UDPServerUDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
DataStringStream: TStringStream;
s: String;
StreamBuf:TMemoryStream;
FS:TFileStream;
Buf:pointer;
AppDir, StartChr, St: String;
StartBit:integer;
begin
StartChr:='SendFile';
AppDir:=ExtractFilePath(Application.ExeName);
StreamBuf:=TMemoryStream.Create;
GetMem(Buf, AData.Size);
try
StreamBuf.CopyFrom(AData, AData.Size);
StreamBuf.SaveToFile(AppDir+'1.str');
StreamBuf.Seek(0,soFromBeginning);
StreamBuf.Read(Buf^, AData.Size);
SetLength(St,AData.Size);
Move(Buf^,St[1],Length(St));
if Copy(St,1,Length(StartChr))=StartChr then
begin
RcvFileName:=Copy(St,Pos('=',St)+1,Length(St)-Pos('=',St));
FS:=TFileStream.Create(AppDir+RcvFileName,fmCreate);
exit;
end
else FS:=TFileStream.Create(AppDir+RcvFileName,fmOpenReadWrite); //вот для этого и я вся эта заморочка. Открываю либо fmCreate либо fmOpenReadWrite для дозаписи, без всяких глобальных переменных и пр.
FS.Seek(0,soFromEnd);
FS.Write(Buf^,AData.Size);
s:='#';
ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, s[1], Length(s));
finally
StreamBuf.Free;
FS.Free;
FreeMem(Buf);
end;
end;
TUser (2004-10-02 10:15:00) [6]Проще - PChar/PAnsiChar
DHDD (2004-10-02 06:38:00) [7]Можно попробовать
ShowMessage(String(Buf^)); // здесь всё нормально, =>
UDPClient.SendBuffer(String(Buf^), Length(St));
Если это будет работать, то ты сразу поймёшь
Германн (2004-10-02 04:50:00) [8]s[1] - указатель на первый байт области памяти, где записана сама строка, s - указатель на область памяти, где хранится "служебная" информация о строке. Кроме того случая, когда строка объявлена как string[...] или когда выключена опция {$H-}
Defunct (2004-10-02 04:30:00) [9]> т.к. следом за строкой цепляются двоичные данные
куда они цепляются?
в коде ничего никуда не цеплялось.
и никто не отменял SetLength(S, новая длинна).
imho для пересылки файлов лучше использовать TCP сокет и SendStream.
здесь ошибка
> UDPClient.SendBuffer(S[1], SizeOf(St));
UDPClient.SendBuffer(S[1], Length(St));
> s[1] а не просто s??
потому что S - указатель на строку.
S[1] - первый символ строки.
> почему SizeOf(Buf)
Buf : Pointer,
SizeOf(Pointer) = 4 всегда.
Германн (2004-10-02 04:20:00) [10]SizeOf(Buf) - возвращает размер переменной Buf. А она - pointer, а Pointer на сей момент - 4 байта. А на что он указывает на сей момент - никого не волнует при вызове SizeOf()!
s[1] - указывает на первый байт области памяти, где записана сама строка. Т.е. на первый символ самой строки.
denkop (2004-10-02 03:24:00) [11]Defunct >> т.к. следом за строкой цепляются двоичные данные
panov >> спасибо, работает. а можно немного пояснений, почему s[1] а не просто s?? и почему SizeOf(Buf) по прежнему возвращает 4??
Defunct (2004-10-02 02:20:00) [12]почему бы не сделать так?
UDPClient.SendBuffer(S[1], SizeOf(St));
для чего там применять Pointer?
panov (2004-10-02 02:14:00) [13]
var
s: String;
p: Pointer;
begin
...
Move(s[1],p^,Counter);