Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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:

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;//
<----- Вот здесь AV и всплывает !
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
1-21125
Metotrone
2002-09-24 17:54
2002.10.07
IconExclamation


1-20986
Паша
2002-09-26 16:05
2002.10.07
Вопрос по FileMapping


1-21051
UnDISCOvery
2002-09-26 16:55
2002.10.07
Как мне создать форму во вторичном потоке ?


4-21321
Alex870
2002-08-19 23:01
2002.10.07
Консольное приложение


14-21220
AL2002
2002-09-11 18:17
2002.10.07
Кто-то знает, где качнуть





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский