Форум: "Сети";
Текущий архив: 2002.10.07;
Скачать: [xml.tar.bz2];
ВнизКак послать файл с ServerSocket и принять его на ClientSocket? Найти похожие ветки
← →
kosmach (2002-08-05 10:17) [0]У ServerSocket есть три до боли простых по своей логике метода:
SendText, SendBuffer и SendStream. Первые два прекрасно работают, впрочем последний тоже работает, данные то клиенту приходят и правильно приходят, но сам он выдает ошибку: "Access violation at adress 00000000",;
Вот код сервера:
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
FS: TFileStream;
St: String;
begin
St:=Socket.ReceiveText;
if St="Send" then begin
try
FS:=TFileStream.Create("file.txt", fmOpenRead);
Socket.SendStream(FS);
finally
FS.Free;
end;
end;
end;
А вот клиента:
procedure TForm1.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
FS: TFileStream;
buf: PChar;
size: longint;
begin
Size:=Socket.ReceiveLength;
GetMem(Buf, Size);
Socket.ReceiveBuf(buf^,size);
FreeMem(buf);
end;
Вроде бы все просто, а не работает, даже предположить не могу, что не так, может кто-нибудь, что-нибудь заметит.
← →
Digitman (2002-08-05 11:01) [1]>>даже предположить не могу, что не так
Кто за тебя будет на стороне клиента создавать объект класса TFileStream ? Ты этого не делаешь, вот и получаешь AV
← →
kosmach (2002-08-05 11:23) [2]Клиентский код я привел просто для примера. На самом деле я делаю так:
procedure TForm1.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
FS: TFileStream;
buf: PChar;
size: longint;
begin
Size:=Socket.ReceiveLength;
GetMem(Buf, Size);
Socket.ReceiveBuf(buf^,size);
if not FileExists("DL\file.txt") then
try
FS:=TFileStream.Create("DL\file.txt", fmCreate);
finally
FS.Free;
end;
try
FS:=TFileStream.Create("DL\file.txt", fmOpenReadWrite);
FS.Seek(0, soFromEnd);
FS.WriteBuffer(buf^, Size);
finally
FS.Free;
end;
FreeMem(buf);
end;
Вобщем, логика такая, там я отсылаю поток, который или весь сразу, если файл маленький, или по частям приходит к клиенту, но в любом случае, клиент все что ему пришло считывает в буфер, а уже потом в или в файл, или в поток или еще куда, т.к. метода для приема потока нет.
← →
Digitman (2002-08-05 11:48) [3]1. Вот эта строчка вполне может дать AV
FS.WriteBuffer(buf^, Size);
правда, не с такими параметрами, что ты привел.
2. Зачем 2 раза создавать объект TFileStream ? Что, разве нельзя , создав единожды объект, дозаписать в конец файла (нового или существующего) очередной блок принятых реально данных ?
И на какой же строчке ты получаешь AV ?
← →
ACR (2002-08-05 12:02) [4]Digitman главный спец па сокетам :-)
напиши статью пра сокеты в асинхронном режиме
пра то как палезна пользовать OnWrite
и как реализавать машину состояний :-)
а то постоянно отвечаешь... отвечаешь...
а вот если все тваи ответы собрать то очень хорошая статья получится
нет я не для себя прашу
у меня давно имеются компаненты
TACRServerSocket
TACRClientSocket
которые нифига не поточные а об"екта передающие ;-)
это я за всех тупых людей прашу...
хатя я тоже тупой......
← →
kosmach (2002-08-05 12:06) [5]AV я получаю не на клиенте, то как я дописываю, создавая новый объект или дописывая в старый, не имеет значения. Клиент прекрасно считывает в буфер все что ему пришло. Я пробовал послать маленький текстовый файл, который полностью принял в буфер за один раз. А где она AV выдает я не знаю, она никакую конкретную строчку не помечает, но явно где-то на сервере.
← →
Digitman (2002-08-05 12:11) [6]>ACR
Не обижайся, но если уж я и найду время и сподоблюсь-таки статью написать, то она будет по-русски. По всем правилам русского языка. Тебе ее читать, inho, тяжеловато будет.
← →
kosmach (2002-08-05 12:17) [7]Люди, а как же я, может кто-нибудь посоветует как подругому послать файл.
← →
Digitman (2002-08-05 12:19) [8]>kosmach
(05.08.02 10:17)
>>"AV я получаю не на клиенте.."
(05.08.02 12:06)
>>"..данные то клиенту приходят и правильно приходят, но сам он выдает ошибку.."
А эту несуразицу как прикажешь понимать ? Изволь уж выражаться точно.
1. >> "А где она AV выдает я не знаю, она никакую конкретную строчку не помечает"
Кто - "она" ? Почему кто-то должен тебе что-то "помечать" в run-time ?
2.>> ".. но явно где-то на сервере."
На основании чего такая уверенность ?
← →
kosmach (2002-08-05 12:27) [9]В таком случае объясни мне - полному чайнику, как мне определить где у меня AV. Обычно в run-time Delphi помечает зеленой стрелочкой где застряла, по крайней мере я это так понимаю. Тут ничего подомного нет.
А насчет ".. но явно где-то на сервере." извени, может я и поторопился.
← →
Digitman (2002-08-05 12:31) [10]>>"..Delphi помечает зеленой стрелочкой где застряла.."
что есть "зеленая стрелочка" ? Почему именно - "зеленая" ? А если у меня она - серо-буро-малиновая, что это меняет в принципе по-твоему ?
что значит - "застряла" ?
Какое приложение ты отлаживаешь - серверное или клиентское ? Используешь ли Delphi integrated bebugging tools для отладки ?
← →
kosmach (2002-08-05 12:39) [11]Господи, как все сложно, я таких слов даже и не знаю.
Рассказываю:
Я создал форму, на нее поместил два компонента ServerSocket и ClientSocket, присвоил ClientSocket.host="127.0.0.1", поставил одинаковый порт у Server и у Client. После чего, по нажатии кнопочки ClientSocket.Open:=True, а по нажатии другой кнопочки ClientSocket.SendText("Send"); Остальной код ты видел. Затем я нажимаю "Run(F9)". Вот и все, а Delphi integrated bebugging tools я не пользуюсь, так как скорее всего не знаю что это такое.
← →
Digitman (2002-08-05 12:51) [12]Сложно, говоришь ? Разговор не получится, извини.
Я не знаю, как тебе "на пальцах" объяснить вещи, которые ты хоть в минимальном объеме, но просто обязан познать перед тем как заниматься программированием/отладкой приложений Win32 вообще и программированием/отладкой сетевых приложений в среде Делфи в частности.
← →
kosmach (2002-08-05 13:07) [13]Раз уж ты такой "модный", то мог бы не задирать так высоко нос, а посоветовать что-нибудь дельное, если не по Socket"ам, то хоть по тому, что ты мне там наговорил: по поводу отладки и прочего. А что касается Socket"ов то действительно напиши статью, что-бы тот кто дорос до этого, тот бы понял как делать, а кто нет - понял, что нужно еще многому учиться. Вобщем, вместо того, чтоб говорить "...обязан познать...", посоветовал бы как это сделать.
Одно утешает, хоть поорали друг на друга вдоволь, а с отправкой файлов, рано или поздно я все равно разберусь.
← →
Digitman (2002-08-05 13:14) [14]>kosmach
"что-нибудь дельное" я тебе уже посоветовал : разберись и укажи, на какой строчке ты получаешь AV - после этого я скажу тебе, источник ошибки. Для этого в Делфи есть встроенный интегрированный отладчик, читать лекцию по использованию которого у меня нет ни малейшего желания.
← →
kosmach (2002-08-05 13:23) [15]Что такое внутренний отладчик я знаю, да и пользоваться им мне приходилось. В данном случае, я прохожу полностью процедуру отпрвки потока с сервера, после чего еще пару раз нажав F7 выскакивает сообщение об AV.
← →
Digitman (2002-08-05 13:47) [16]Ну так на какой строчке-то AV ?? Ты F7 для чего жмешь-то ? Просто так ? Или-таки - для контроля исполнения конкретной строчки ?
Где , в каком месте ты ставишь точку останова ?
← →
kosmach (2002-08-05 13:52) [17]Последняя строчка, на которой я жму F7 это FS.Free в procedure TForm1.ServerSocketClientRead, после чего всякое выделение пропадает, проходит несколько секунд, и вместо того, чтобы перейти к обработчику события ClientSocket onRead, выскакивает ошибка.
← →
Digitman (2002-08-05 14:12) [18]Эту ошибку я уже тебе указал в постинге от (05.08.02 11:48)
Конечно, там я обращался не к тебе, а к Пушкину, и написал там полную чушь - чего ее читать-то ?
Поэтому, очевидно, ты его (постинг) проигнорировал, даже не вникнув.
Вот - более-менее корректный код взамен соответствующего:
FS:=TFileStream.Create("DL\file.txt", fmOpenReadWrite);
try
FS.Seek(0, soFromEnd);
FS.WriteBuffer(buf^, размер_реально_прочитанных_данных_возвращенный_ф-цией_ReceiveBuf);
finally
FS.Free;
end;
← →
kosmach (2002-08-05 14:28) [19]Во-первых, Пушкин здесь не причем, все что ты мне написал, я достаточно внимательно прочитал, во-вторых, я зделал все как ты мне "велел". Поток для записи я открыл еще в ClientSocket.onConnect, а в ClientSocket.onRead сделал следующее
procedure TForm1.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
buf: PChar;
size, s: longint;
begin
Size:=Socket.ReceiveLength;
GetMem(Buf, Size);
try
S:=Socket.ReceiveBuf(Buf^, Size);
FS.WriteBuffer(buf^, S);
finally
FreeMem(buf);
end;
end;
И поверь мне, ничего не изменилось.
← →
Digitman (2002-08-05 14:44) [20]Я тебе еще раз повторяю :
FS.WriteBuffer(buf^, размер_реально_прочитанных_данных_возвращенный_ф-цией_ReceiveBuf (!!!!!!!!!!!!!!!!!!));
Что у тебя содержит переменная Size на момент вызова WriteBuffer() ? Если ты считаешь, что Size - это размер реально прочитанных данных, то - вперед, в хэлп по методам ReceiveLenght() и ReceiveBuf(). С ЭТОГО надо начинать - с внимательнейшего чтения хэлпа ! А не со слепого передирания неизвестно где взятых "корявых" примеров.
← →
kosmach (2002-08-05 14:50) [21]В хэлп я загляну, а вот ты - воспитатель х..в, уже не одному десятку человек сказал вот эту фразу: "размер_реально_прочитанных_данных_возвращенный_ф-цией_ReceiveBuf (!!!!!!!!!!!!!!!!!!)", и хоть бы раз забил на свою вонючую принципиальность, и прямо сказал как надо делать.
← →
kosmach (2002-08-05 14:56) [22]Извени
← →
kosmach (2002-08-05 15:01) [23]Вот мой код, уже указанный выше:
S:=Socket.ReceiveBuf(Buf^, Size);
FS.WriteBuffer(buf^, S);
Разьве S - это не то, что возвратила функция ReceveBuf?
← →
Digitman (2002-08-05 15:15) [24]Разговор окончен. Ты показал себя.
← →
ACR (2002-08-05 18:25) [25]>Digitman © Снобизм тежолая болезнь
>kosmach © (05.08.02 14:28)
ReceiveBuf могет -1 вернуть прикинь какая лажа выйдет...
← →
cyborg (2002-08-05 21:39) [26]kosmach © напиши полный код твоих сокетов, тут нихрена не понятно, в одном отрывке у тебя одно, в другом другое, где-то кастрировано и хочешь что бы тебе дали ответ на то, что ты сам не можешь сказать что.
И буфер нужно делать на Pointer-е, а не на PChar-е.
← →
karbo (2002-08-06 03:50) [27]В коде сервера в самом деле зарыта AV:
<----- Вот здесь AV и всплывает !
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
FS: TFileStream;
St: String;
begin
St:=Socket.ReceiveText;
if St="Send" then begin
try
FS:=TFileStream.Create("file.txt", fmOpenRead);
Socket.SendStream(FS);
finally
FS.Free;//
end;
end;
end;
Почему так происходит, объяснить не берусь, но совет дам : не надо так быстро убивать FS после Socket.SendStream.
Лучше объявить FS как глобальную переменную и вызывать ее Create и Free только один раз - где нибудь в FormCreate и FormClose.
← →
kosmach (2002-08-06 07:11) [28]
> karbo ©
Я это с самого начала говорил, только создовать поток в FormCreate я не могу, так как надо будет слать несколько файлов и влюбом случае, придется убивать поток, а потом создовать его, с новым именем файла.
А Вообщето, я считал, что можно ограничиться try ... finally...end; и никаких ошибок быть не должно.
> cyborg ©
Согласен, вчера я все время чего-то переделывал, по советам некоторых, вот полный код:
var
Form1: TForm1;
FS: TFileStream;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket.Open;
end;
procedure TForm1.ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
if FileExists("DL\file.txt") then DeleteFile("DL\file.txt");
FS:=TFileStream.Create("DL\file.txt", fmCreate);
end;
procedure TForm1.ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
FS.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ClientSocket.Close;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
ClientSocket.Socket.SendText("Send");
end;
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
FS: TFileStream;
St: String;
buf: PChar;
size: longint;
begin
St:=Socket.ReceiveText;
if St="Send" then begin
try
FS:=TFileStream.Create("file.txt", fmOpenRead);
Socket.SendStream(FS);
finally
FS.Free;
end;
end;
end;
procedure TForm1.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
buf: PChar;
size, s: longint;
begin
Size:=Socket.ReceiveLength;
GetMem(Buf, Size);
try
S:=Socket.ReceiveBuf(Buf^, Size);
FS.WriteBuffer(buf^, S);
finally
FreeMem(buf);
end;
end;
end.
← →
kosmach (2002-08-06 07:16) [29]
> ACR ©
Ну и черт с ним, пускай возвращает 1, это значит, что реально я принял 1 байтик, ну и не хай, остальные в следующий раз приму и запишу куда надо.
← →
ACR (2002-08-06 08:04) [30]>karbo ©
Сматрите внимательно:
try
FS:=TFileStream.Create("file.txt", fmOpenRead);
Socket.SendStream(FS); < Вот эта строчка никуда ничего неотправляет! ана всеголишь долбится в сокет на предмет готовности передачика и ставит байтики в очередь на отпраку
finally
FS.Free; // здесь сокет вожможно еще передает твой паток по сети а ты этот паток беспащадно убиваешь... кто ты после этого?
Granted AV Coder!
end;
>kosmach ©
не 1 а (-1) чуешь разницу?
а еще ReceiveLength может вернуть 0 представляешь какая анархия в твоем коде будет?
← →
kosmach (2002-08-06 08:16) [31]
> ACR ©
Насчет
> не 1 а (-1) чуешь разницу?
> а еще ReceiveLength может вернуть 0
все ясно, разберусь. А вот как быть с
> try
> FS:=TFileStream.Create("file.txt", fmOpenRead);
> Socket.SendStream(FS); < Вот эта строчка никуда ничего
> неотправляет! ана всеголишь долбится в сокет на предмет
> готовности передачика и ставит байтики в очередь на отпраку
>
> finally
> FS.Free; // здесь сокет вожможно еще передает твой паток
> по сети а ты этот паток беспащадно убиваешь... кто ты после
> этого?
> Granted AV Coder!
> end;
Подскажи, пожалуйста
← →
ACR (2002-08-06 08:46) [32]>kosmach ©
вот тебе поле для иследований
глобальная переменная
ReadyToTransmit : boolean;
OnFormCreate
{
ReadyToTransmit := false;
}
OnClientDisconnect
{
ReadyToTransmit := false;
}
OnServerSockeClientWrite !
{
ReadyToTransmit := trueж < Здесь передачик либо только что инициализировлся и готов передовать либо только что передал последний байт из буфера и сново готов передавать
}
OnServerSocketClientRead
{
S := CreateStream;
Socket.SendStream(S);
while (not ReadyToTransmit) do Application.ProcessMessage;
S.Free;
try...finally ваще убери они не для этого предназначены
}
думаю разберешся с моим псевдо кодом
от AV ты избавишся... даже возможно все будет работать
но всеравно у тя получится полная лажа...
St:=Socket.ReceiveText;
if St="Send" then // ты уверен что тут получишь иммено Send?
можешь сначало получить "S" патом "е" и т.д. а можешь "Se" а патом "end" а St никогда небудет равна "Send" хотя если сеть быстрая то все будет тип топ
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2002.10.07;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.012 c