Конференция "Сети" » Как правильно послать файл через TcpServer & TcpClient ? [D7, WinXP]
 
  • Andrewtitoff © (18.01.08 10:57) [0]
    Пытаюсь послать файл, файл посылается, но прога все время вываливается с ошибками:
    Access violation, Canvas does not allow drawing... =(((
    И как при приеме узнать размер пересылаемого файла что бы засунуть его в ReceiveBuf.., SizeOf(Buf) возвращает все время 4 ... =(((
    Вот текст моей программы:

    ================================================
    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Sockets, StdCtrls;

    type
     TMyChat = class(TForm)
       Label1: TLabel;
       Label2: TLabel;
       Label3: TLabel;
       RemoteHost: TEdit;
       RemotePort: TEdit;
       LocalPort: TEdit;
       Display: TMemo;
       Edit: TEdit;
       Connect: TButton;
       TcpServer1: TTcpServer;
       TcpClient1: TTcpClient;
       SendFile: TButton;
       procedure TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
       procedure SendClick(Sender: TObject);
       procedure ConnectClick(Sender: TObject);
       procedure SendFileClick(Sender: TObject);
       procedure FormClose(Sender: TObject; var Action: TCloseAction);
     private
       { Private declarations }
     public
       { Public declarations }
     end;

    var
     MyChat: TMyChat;

    implementation

    {$R *.dfm}

    procedure TMyChat.ConnectClick(Sender: TObject);
    begin
    TcpServer1.LocalPort := LocalPort.Text;
    TcpServer1.Active := True;
    TcpClient1.RemotePort := RemotePort.Text;;
    TcpClient1.RemoteHost := RemoteHost.Text;;
    TcpClient1.Active := True;
    end;

    procedure TMyChat.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    TcpServer1.Active := False;
    TcpClient1.Active:= False;
    TcpClient1.Disconnect;
    end;

    procedure TMyChat.SendFileClick(Sender: TObject);
    var
    asd:Tmemorystream;
    begin
    asd := TMemoryStream.Create;
    asd.Position:=0;
    asd.LoadFromFile('c:\1.txt');
    asd.Position:=0;
    TcpClient1.Active := True;
     try
       if TcpClient1.Connect then
         begin
         TcpClient1.SendStream(asd);
         end;
     finally
       TcpClient1.Disconnect;
     end;
    asd.free;
    end;

    procedure TMyChat.TcpServer1Accept(Sender: TObject;
     ClientSocket: TCustomIpClient);
    var
        s:string;
        asd:tmemorystream;
        len:integer;
        buf:pointer;
     begin
    asd:=TMemoryStream.Create;
    asd.Position:=0;
    len:= ClientSocket.ReceiveBuf(buf,192,0);
    asd.WriteBuffer(buf,len);
    asd.SaveToFile('c:\000.txt');
    asd.Free;
    FreeMem(Buf);
    clientsocket.Close;
    ShowMessage('clientsocket.Close');
    end;

    end.
    ================================================

  • Сергей М. © (18.01.08 12:53) [1]

    > SizeOf(Buf) возвращает все время 4


    А сколько он, по твоему, должен возвратить, если переменная buf имеет указательный тип ?
  • Slym © (18.01.08 13:20) [2]
    Andrewtitoff ©   (18.01.08 10:57)
    ClientSocket.ReceiveBuf(buf,192,0);

    а память выделит папа Карло?
    GetMem(buf,1024);
    len:= ClientSocket.ReceiveBuf(buf,1024,0);
    asd.WriteBuffer(buf,len);
    FreeMem(buf)


    или
    var buf:array[0..1023] of byte;

  • Andrewtitoff © (18.01.08 13:55) [3]
    2 Slym
    Спасибо, тока ничего не изменилось.. =((( тока если в ClientSocket.ReceiveBuf размер пишу 1024 как у тебя то почему то Len = -1, а если 192 как раньше(192 - это размер пересылаемого мною при тестировании файла) то все та же ошибка "Canvas does not allow drowing"... =(((
     
    2 Сергей М.
    Так а как мне узнать размер пересылаемого файла?, раньше в TClientSocket
    писалось Len:=Socket.ReceiveLength;, а теперь как?...  =((((
  • Сергей М. © (18.01.08 15:02) [4]

    > как мне узнать размер пересылаемого файла?


    А ты его отправлял, этот размер, прежде чем его принимать ?


    > раньше в TClientSocket
    > писалось Len:=Socket.ReceiveLength


    Раньше у власти были коммуняки, мало ли какая фигня при них "писалась")


    > а теперь как?


    А теперь следует думать головой - если размер ты не отправил, то и принять его не сможешь.
  • Andrewtitoff © (18.01.08 15:16) [5]
    2 Сергей М
    Ясно, ну с размером конечно это не очень хороше, но в общем то мне все понятно, отправлю - не вопрос...
    Так а в чем у меня еще ошибка то, я когда тестиркю размер файла то знаю, и его вписываю, тока пересылать то он пересылается, тока после этого программа с треском вываливается или всю систему вешает...  =(((
  • Сергей М. © (18.01.08 15:18) [6]

    > пересылать то он пересылается


    Где ?!!
    Покажи хоть малейший намек на это в приведенном тобой коде ..
  • Palladin © (18.01.08 15:21) [7]
    а он его мысленно телепартирует :)
  • Сергей М. © (18.01.08 15:23) [8]

    > раньше в TClientSocket


    А теперь он типа не моден)
  • Andrewtitoff © (18.01.08 16:04) [9]
    2 Сергей М
    Ну я тестирую на одном компе, пишу в RemoteHost - LocalHost, а RemotePort такой же как и LocalPort, файл копируется.., если не веришь могу исходник полностью кинуть....
    А по поводу не моден ответить нечего, типа того... =))), просто я пишу на 2007 дельфях, боюсь как бы в 2008 - х их уже небыло... =))))
  • Сергей М. © (18.01.08 16:50) [10]

    > тестирую на одном компе


    "на одном компе" <> "через Тырнет"

    Запомни как тверди денно и нощно мантру.


    > я пишу на 2007 дельфях, боюсь как бы в 2008 - х их уже небыло


    Угу.

    А то что в 2008 окажутся TTCPClient/Server - это в Библии, наверно,  записано)

    Еще таз для танкистов - если передающая сторона не скажет принимающей объем следом передаваемых данных, принимающая сторона не будет иметь никаких гарантий корректности размера и содержимого принятых данных.
  • DVM © (18.01.08 16:59) [11]

    > Andrewtitoff ©   (18.01.08 16:04) [9]


    > Ну я тестирую на одном компе, пишу в RemoteHost - LocalHost,
    >  а RemotePort такой же как и LocalPort, файл копируется

    Советую потестить, например, через GPRS - очень хороший тест надежности копирования.
  • Andrewtitoff © (18.01.08 17:51) [12]
    2 Сергей М
    Ну а что толку пытаться тестить в реальных условиях если она как ты говоришь и через тырнет не работает....
    Не ну этого конечно тож никто не гарантировал что они в 2008-ой дельфе будут, но по крайне мере раз они их начиная с 7-щй дельфи выставляют на показ а TClientSocket в панели непоказывают хотя они до сих пор и присутствуют - то я считаю что вероятнее всего рано или поздно они на них окончательнно перейдут....
    А по поводу объема я и не спорю просто пока тестирую - шлю определенный файл, размер которого мне известен и указываю явным образом его размер так что тут пока что никаких проблем не может быть, но прога то до сих пор толком не работает так что дело не в размере...
    Серега если тебе не сложно не мучай меня дурака напиши как это делается,
    ес ли ты знаешь как это пишется - то я не думаю что это же займет минут 5 написать простенькую прогу и выложить исходник, я думаю ьебе многие будут благодарны за это!!!  =))))
    2 DVM ©
    Да я понимаю что придется тестить в реальных условиях, тока для этого она дорлжна сначала хотябы так заработать....
  • Andrewtitoff © (18.01.08 18:03) [13]
    2 Сергей М.
    Мне нкжен то пример такой жк как
    http://pda.delphimaster.net/?id=1190918176&n=4
    тока рабочий и через TcpServer & TcpClient =)))
    Заранее благодарен, надеюсь я не очень мнлго прошу... =)))
  • Сергей М. © (19.01.08 18:36) [14]

    > Мне нкжен то пример
    </I
    > тока рабочий

    >

    Предположим, ты его получил.
    Что-то ты изменил в нем, пример перестал работать. Что дальше? Опять гундеть-канючить будешь ?)
  • Andrewtitoff © (19.01.08 23:39) [15]
    2 Сергей М.
    Да ладно те..., сразу оскорблять.., я конечно не великий программер как ты, но не до такой степени лапух что не смогу переделать под себя элементарный пример...,
    Если лень -так и скажи..., а если нет - то кинь пример и забудем, обещаю что больше канючить небуду! =))))
  • Сергей М. © (20.01.08 00:18) [16]

    > не до такой степени лапух


    Ты лапух не "в степени".
    Ты просто лАпух.
    А "лапухам не до такой степени" не пристало учить и знать Паскаль.

    Возражать имеешь ?)

    Какие тебе, нахрен, сети и компоненты ?
    КАКОГО хрена ты нетипизированным var-параметром передаешь buf ?

    Бегом учить паскаль !!

    И чтоб тебя здесь не было, пока не выучишь сам язык, прежде чем его применять для даже элементарных задач)
  • MetalFan © (20.01.08 02:15) [17]

    >  [16]

    +1

    > но не до такой степени лапух что не смогу переделать под
    > себя элементарный пример...

    так если он для тебя элементарный, то зачем просишь его тебе написать???
  • Andrewtitoff © (20.01.08 14:25) [18]
    2 Сергей М.
    Даа.., видиммо для тебя это тоже не такая элементарная задача иначе бы просто прислал бы пеример и не гнул пальцы....
    И при чем тут паскаль?, писал я немного в свое время и на паскале, тока писал то что мне надо был, а файли ки мне надо было тока маленткие копировать и т.д. по этому мне хватало read write... и читал - писал себе спокойно по байтам....
    И как же ты хочешь что бы я что то изучал - если сам обьяснять не хочешь....

    2 MetalFan
    Я  имел ввиду для него элементарный - видимо ошибся...
  • Сергей М. © (20.01.08 19:38) [19]

    > иначе бы просто прислал бы пеример


    Он тебе не поможет.
    Потому что когда тебе говорят про фому, ты все одно гнешь про ерему.

    Тебе в [1] был задан вопрос, правильный самостоятельный ответ на который - шаг к самостоятельному решению задачи.
  • Andrewtitoff © (20.01.08 20:28) [20]
    Ну уж это то наверное мне решать поможет он мне или нет...
    А по поводу указателей - это да у меня с этим туго..., как то не пользовался в свое время - вот и нехватает знаний...  =(((
    Но я кстати пробовал писать и Buf^ и @Buf тока от этого ничего не менялось... =)))
    Так что если не хочешь помоч - так и скажи, или обьясни как и что делается....
  • Сергей М. © (20.01.08 20:31) [21]

    > если не хочешь помоч - так и скажи


    см. [1]
  • Сергей М. © (20.01.08 20:39) [22]

    > пробовал писать и Buf^ и @Buf тока от этого ничего не менялось


    В данном примере правильным будет Buf^.
    А вот почему правильной будет именна такая конструкция - это тебе задание на дом для самостоятельного изучения, это одна из основ языка, без знания которых дальнейшие рассуждения про бессмысленны.
  • Andrewtitoff © (20.01.08 20:48) [23]
    Так почему у меня и с Buf^ все тоже самое как и с Buf, и возвращает тоже 4...
  • Сергей М. © (20.01.08 21:00) [24]

    > почему у меня и с Buf^ все тоже самое как и с Buf


    А какое отношение это имеет к


    > возвращает тоже 4


    ?

    Никакого.

    Я тебе в [1] задал вопрос, ты до сих пор его игнорируешь. И долго еще эта сказка про белого бычка будет тянуться ?
  • Andrewtitoff © (20.01.08 22:00) [25]
    Да я понял уже давно эту свою ошибку что при описании указателя в статической области памяти будет выделено 4 байт - поэтому и возвращает размер переменной то есть 4 и возвращает....
  • Сергей М. © (20.01.08 22:11) [26]
    Чудесно.
    Приводи скорректированный вариант своего кода с учетом этой важной поправки..
  • Andrewtitoff © (21.01.08 09:36) [27]
    2 Сергей М.
    Чет я совсем ниче не понимаю..., вот скорректированный код, но все работает как и прежде, вылетает с ошибкой "Canvas does not allow drawing"... =(((
    Так в чем ошибка то?, тока не говори про ДНК - это старая шутка...  =)))


    procedure TMyChat.TcpServer1Accept(Sender: TObject;
     ClientSocket: TCustomIpClient);
    var
        asd:tmemorystream;
        len:word;
        buf:pointer;
     begin
    len:=192;
    asd:=TMemoryStream.Create;
    GetMem(buf,len);
    len:= ClientSocket.ReceiveBuf(buf^,len,0);
    asd.Position:=0;
    asd.WriteBuffer(buf^,len);
    asd.SaveToFile('c:\000.txt');
    asd.Free;
    FreeMem(Buf);
    clientsocket.Close;
    ShowMessage('clientsocket.Close');
      end;

  • Сергей М. © (21.01.08 09:49) [28]
    А где соответствующий скорректированный код сервера ?

    И чему равны значения св-ва BlockMode у клиента и у сервера ?
  • Andrewtitoff © (21.01.08 10:01) [29]
    В смысле код сервера?, а я что прислал? (procedure TMyChat.TcpServer1Accept)

    значения св-ва BlockMode у клиента и у сервера равны bmBlocking bmThreadBlocking соответственно.
  • Сергей М. © (21.01.08 10:32) [30]

    > а я что прислал?


    А где там коррекция в части ^?
    Где там выделение памяти под buf ?
    Откуда взялось 192 ?
    Где анализ результата вызова ReceiveBuf ?
    Где обработчик OnGetThread ?
    Где создание доп.потока ?
    Почему при bmThreadBlocking работа с клиентом идет в OnAccept, а не как и положено - в доп.потоке, который должен быть создан тобой в OnGetThread ?

    Нет этого ничего !
    Вот как будет, так и разговор продолжим.
  • Andrewtitoff © (21.01.08 10:57) [31]
    В смысле?
    Может я чего то недопонимаю  - подскажи тогда дураку...

    коррекция в части ^ вот, а где еще чего надо?
    len:= ClientSocket.ReceiveBuf(buf^,len,0);
    asd.WriteBuffer(buf^,len);

    192 - это просто размер пересылаемого мною файла...

    А можно поподробнее про анализ результата вызова ReceiveBuf, а то чет я непонимаю чего там как и вообще зачем анализировать?

    А что в обработчик OnGetThread писать надо?

    И как создавать доп. поток?

    Мне нигде ненайти ничего по работе с TcpServer и TcpClient..., нашел примеры тока с Receiveln, SendLn..., там все ясно но там все идет в OnAccept...

    Кстати ошибку я вроде нашел.., там просто TcpClient1.Active := True нужно было писать не в прцедуре ConnectClick a уже в SendFileClick...
    Теперь прога не вылетает тока почему то обрезает первые 26 байт содержимого файла и добовляет соответственно 26 пробелов в конец... =(((
  • Andrewtitoff © (21.01.08 11:11) [32]
    перенес ве это дело в GetThread, та же история... =(((

    procedure TMyChat.TcpServer1GetThread(Sender: TObject;
     var ClientSocketThread: TClientSocketThread);
    var
    s:string;
        asd:tmemorystream;
        len:word;
        buf:pointer;
     begin
    len:=192;
    asd:=TMemoryStream.Create;
    GetMem(buf,len);
    TcpServer1.ReceiveBuf(buf^,len,0);
    asd.Position:=0;
    asd.WriteBuffer(buf^,len);
    asd.SaveToFile('c:\000.txt');
    asd.Free;
    FreeMem(Buf);
    TcpServer1.Close;
      end;

  • Сергей М. © (21.01.08 11:15) [33]
    Ты вообще справку к этим компонентам читать собираешься ?
  • Andrewtitoff © (21.01.08 11:24) [34]
    Так а где ее взять то?, в дельфе написано:
    Delphi 2007 for Win32  
    Using Socket Components
    See Also
    Collapse AllThe Internet category includes three socket components that allow your network application to form connections to other machines, and that allow you to read and write information over that connection. These are:
    TTcpServer
    TTcpClient
    TUdpSocket
    Associated with each of these socket components are socket objects, which represent the endpoint of an actual socket connection. The socket components use the socket objects to encapsulate the socket server calls, so that your application does not need to be concerned with the details of establishing the connection or managing the socket messages.

    If you want to customize the details of the connections that the socket components make on your behalf, you can use the properties, events, and methods of the socket objects.
  • Сергей М. © (21.01.08 11:25) [35]

    > 192 - это просто размер пересылаемого мною файла.


    А если файл будет другого размера ? Что, править и перекомпилировать проект будешь ?


    > можно поподробнее про анализ результата вызова ReceiveBuf


    Справку к этому методу ты проштудировал ? Что тебе там непонятно ?
  • Сергей М. © (21.01.08 11:34) [36]
    У и зачем использовать компоненты, для которых отсутствует справка ?
    Не ты ли тут трындел про поддержку компонентов в последующих версиях ?
    Отсутствие (частичное или полное) справки к этим компонентам в D2007 должно навести на мысль, что поддержка в будущем этих компонентов под большим вопросом.
  • Andrewtitoff © (21.01.08 11:37) [37]
    Нет, с Receiveln, SendLn я вроде разобрался, покрайне мере пример чата из 7-ых дельфей переделанный мною под TcpServer и TcpClient нормально работает.., буду пересылать размер...

    >Справку к этому методу ты проштудировал ? Что тебе там непонятно ?

    Так а где ее взять то?, у меня во первых с английским не очень, а во вторых все что есть в справке:
    Delphi 2007 VCL Win32 Reference  

    TCustomWinSocket.ReceiveBuf Method
    TCustomWinSocket Class | TCustomWinSocket Members | ScktComp Namespace | Description | See Also
    Collapse AllReads up to Count bytes from the socket connection into the Buf parameter.

    Pascal
    function ReceiveBuf(var Buf; Count: Integer): Integer;
    Description
    Use ReceiveBuf to read from the socket connection in the OnSocketEvent event handler of a Windows socket object or in the OnRead or OnClientRead event handler of a socket component. ReceiveBuf returns the number of bytes actually read. If no bytes are read, ReceiveBuf returns –1.

    ReceiveBuf only works in response to a read notification to a non-blocking windows socket. Blocking sockets must use a TWinSocketStream for reading. The TWinSocketStream object waits for the remote socket to be ready before transferring information.

    Note:  While the ReceiveLength method can return an estimate of the size of buffer required to retrieve information from the socket, the number of bytes it returns is not necessarily accurate.
  • Andrewtitoff © (21.01.08 11:41) [38]
    Кстати вот так заработало...:

    procedure TMyChat.TcpServer1Accept(Sender: TObject;
     ClientSocket: TCustomIpClient);
    var
    s:string;
        asd:tmemorystream;
        len:word;
        buf:pointer;
     begin
    len:=192;
    asd:=TMemoryStream.Create;
    GetMem(buf,len);
    ClientSocket.ReceiveBuf(buf^,len,0);
    asd.Position:=0;
    asd.WriteBuffer(buf^,len);
    asd.SaveToFile('c:\000.txt');
    asd.Free;
    FreeMem(Buf);
    TcpServer1.Close;
      end;

  • Сергей М. © (21.01.08 11:50) [39]

    > Кстати вот так заработало


    Теперь разнеси своего клиента и сервера по разным углам Тырнета и попытайся передать файл размером более 8 кб. Или попытайся обслужить более чем одного клиента одновременно. Грабли тебе гарантированы.


    > у меня во первых с английским не очень


    Печально. Ничего путного у тебя не получится, пока не выучишь.


    > все что есть в справке


    Это говорит как раз о том, что Борланд прекратил поддержку этих компонентов.

    Продолжай зарабатывать себе геморрой.
  • Andrewtitoff © (21.01.08 12:40) [40]
    >Теперь разнеси своего клиента и сервера по разным углам Тырнета и попытайся передать файл размером более 8 кб

    Вот блин точно..., Len в ReceiveBuf(buf^,len,0); имеет тип word, а он равен 2 байтам т.е. от 0 до 65535...  =((( , а что что бы послать файл побольше его нужно разбивать, или есть какой нить способ?

    >Или попытайся обслужить более чем одного клиента одновременно
    А как сделать то??, хотя для задачи которая на данный момент передомной стоит мне вполне хватит две пары клиент-сервер, но все таки хотелось бы знать и как сделать с несколькими клиентами...  =(((
  • Сергей М. © (21.01.08 13:12) [41]

    > Len в ReceiveBuf(buf^,len,0); имеет тип word


    Ничего подобного.

    В твоей декларации он integer и в прототипе oн тоже integer, так что верхний предел 2гб.

    Да и не в этом дело.

    А дело в том, что результат выполнения ReceiveBuf вовсе не обязан быть равным значению Len - он может быть и меньшим чем Len, вплоть до 0 или -1. Ты этот факт в своем коде никак не учитываешь, потому и грабли тебе обеспечены. Я же сказал тебе - анализируй результат !
  • Сергей М. © (21.01.08 13:14) [42]

    > Canvas does not allow drawing


    Убирай ShowMessage.
  • Andrewtitoff © (21.01.08 13:53) [43]
    А точно, гдето я не там высмотрел, все верно integer... =)))

    >А дело в том, что результат выполнения ReceiveBuf вовсе не обязан быть равным значению Len - он может быть и меньшим чем Len, вплоть до 0 или -1. Ты этот факт в своем коде никак не учитываешь, потому и грабли тебе обеспечены. Я же сказал тебе - анализируй результат !
    Вот блин я написал

    var
        asd:tmemorystream;
        len:integer;
        LenRes:integer;
        buf:pointer;
     begin
    len:=68096;
    asd:=TMemoryStream.Create;
    GetMem(buf,len);
    LenRes:=ClientSocket.ReceiveBuf(buf^,len);
    asd.Position:=0;
    asd.WriteBuffer(buf^,len);
    if LenRes <> len then
    ShowMessage('Ошибка размера : '+Inttostr(LenRes))
    else
    begin
    asd.SaveToFile('c:\000.doc');
    ShowMessage('Файл принят')
    end;
    asd.Free;
    FreeMem(Buf);
    end;


    Теперь прога виснет и неодного мессаджа не показывает...  =((((
  • Andrewtitoff © (21.01.08 13:55) [44]
    Опять ShowMessage?, а почему, при чем тут оно?, и чем можно тогда выводить сообщения?
  • Сергей М. © (21.01.08 13:58) [45]
    Ты по-русски читать умеешь ?

    Сказано же - убирай к чертовой бабушке все свои ShowMessage !)

    Нельзя в доп.потоке обращаться  визуальным VCL-контролам !
  • Сергей М. © (21.01.08 14:00) [46]

    > чем можно тогда выводить сообщения?


    Не надо их ничем выводить.
    Для пошагового контроля за ходом выполнения программы в Делфи существует встроенный отладчик. Только не говори, что первый раз про него слышишь.
    А если все же приспичило выводить, пользуй MessageBox
  • Сергей М. © (21.01.08 14:10) [47]

    > Ошибка размера


    Ошибкой может считаться только LenRes = -1.

    Если LenRes = 0, это означает что партнер закрыл соединение по своей иниативе, считать это ошибкой нельзя.

    Если 0 < LenRes <= Len, то это не ошибка, а вполне штатная ситуация.
  • Andrewtitoff © (21.01.08 14:12) [48]
    Ясно, так а что делать ели размер несовпал?

    Во блин приехали....

    Всю жизнь было так:
    function MessageBox(Text, Caption: PChar; Flags: Longint): Integer;
    а теперь:
    int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)Странно как то... =((((
  • Andrewtitoff © (21.01.08 14:20) [49]
    Ой, эт я опять туплю... =)))
    Просто надо писать Application.MessageBox(Text, Caption: PChar; Flags: Longint): Integer;
  • Andrewtitoff © (21.01.08 14:25) [50]
    Не.., с MessageBox виснет так же как и с ShowMessage...  =((((
  • Сергей М. © (21.01.08 14:31) [51]

    > что делать ели размер несовпал?


    Повторно вызывать ReceiveBuf, запрашивая оставшиеся данные.


    > надо писать Application


    Не надо.


    > с MessageBox виснет


    Отладчик тебе в руки
  • Andrewtitoff © (21.01.08 15:05) [52]
    >Повторно вызывать ReceiveBuf, запрашивая оставшиеся данные.

    Так это что ли вычитать из размера файла то что передалось и вызывать ReceiveBuf уже с Buf = FileSize - ReceiveSize ?
  • Сергей М. © (21.01.08 15:15) [53]
    Да.
  • Andrewtitoff © (21.01.08 15:33) [54]
    Ну вот вроде как заработало, тока чет я переменных по моему лишку напихал.... =)))

    procedure TMyChat.TcpServer1Accept(Sender: TObject;
     ClientSocket: TCustomIpClient);
    var
        asd:tmemorystream;
        len:integer;
        LenRes1:integer;
        LenRes2:integer;
        buf:pointer;
     begin
    len:=68096;
    LenRes1:=Len;
    LenRes2:=0;
    asd:=TMemoryStream.Create;
    GetMem(buf,len);
    asd.Position:=0;
    Repeat
    LenRes1:=ClientSocket.ReceiveBuf(buf^,lenRes1);
    asd.WriteBuffer(buf^,lenRes1);
    LenRes2:=LenRes2+LenRes1;
    if LenRes1 <> len then lenRes1 := len-LenRes2;
    Until LenRes2 = len;
    asd.SaveToFile('c:\000.doc');
    asd.Free;
    FreeMem(Buf);
      end;

  • Andrewtitoff © (21.01.08 15:37) [55]
    Так а как правилино сделать  с :

    >Или попытайся обслужить более чем одного клиента одновременно

    А как сделать то??, хотя для задачи которая на данный момент передомной стоит мне вполне хватит две пары клиент-сервер, но все таки хотелось бы знать и как сделать с несколькими клиентами...  =(((
  • Andrewtitoff © (21.01.08 15:50) [56]
    Просто вообще мне надо что бы моя прога пересылала туда-сюда файлы и что бы можно было управлять ей удаленно.., как это сделать?, я конечно могу сейчас наклепать еще одну связку клиент-сервер и по одной передавать файло, а по другой команды, но я так предполагаю что есть способ лучше
  • Сергей М. © (21.01.08 15:55) [57]

    > А как сделать то?


    Ты еще с работой с одним клиентом не разобрался.

    Разберешься досконально с одним - вот тогда перейдем к многим клиентам.

    А пока вернемся к делам нашим скорбным: предположим, что ReceiveBuf вернул 0 или -1 ...
  • Andrewtitoff © (21.01.08 16:17) [58]
    Так если ноль - то помоему ничего страшного, он просто стока стока же запросит скока и изначально, или тут что то не так?
  • Сергей М. © (21.01.08 16:24) [59]
    0 - это факт штатного закрытия соединения партнером по его инициативе.
    -1 - факт нештатного (аварийного) разрыва соединения (например, уборщица партнера БабКлава выдернула шваброй сетевой шнур из компа или злобные хакеры из Тимбукту перекусили оптоволокно между Бобруйском и СПб)

    Ни тот ни другой случай ты не ожидаешь и никак не реагируешь на них.
  • Andrewtitoff © (21.01.08 16:33) [60]
    Так а как надо реагировать то?, ну с -1 - отдельный разговор хотя бы потому что в вычислениях бред пойдет, но а с нулем то что?, веди при LenRes1=0 оно все равно не равно len которая в данном случае равна 68096 и следовательно LenRes2 = 0 + 0, а  lenRes1 = 68096 - 0 т.е. тем же самым 68096...
  • Andrewtitoff © (21.01.08 16:43) [61]
    Или там заново надо писать  TcpClient1.Active := True;?
  • Сергей М. © (21.01.08 16:53) [62]
    Сам-то как думаешь ?
    Или ты отвык (или никогда не умел ?) думать ?
  • Andrewtitoff © (21.01.08 18:29) [63]
    думаю надо, зачем сразу оскорблять то? =))))
  • Slym © (22.01.08 04:37) [64]
    Коротко и ясно...
    procedure TForm1.TcpServer1Accept(Sender: TObject;
     ClientSocket: TCustomIpClient);
    var
     Stream:TFileStream;
     buf:array[byte] of byte;
     len:integer;
    begin
     Stream:=TFileStream.Create('c:\file_'+FormatDateTime('ddmmyyyy_hhmmss',Now)+'.txt', fmCreate);
     try
       while ClientSocket.Connected do
       begin
         len:=ClientSocket.ReceiveBuf(buf,SizeOf(buf),0);
         if len<=0 then Break;
         Stream.WriteBuffer(buf,len);
       end;
     finally
       Stream.Free;
     end;
    end;

  • Slym © (22.01.08 04:39) [65]
    Сохраняется сразу в файл, концом передачи/файла считается отключение клиента...
    если клиента тупо оборвало, всеравно считается концом передачи
  • Slym © (22.01.08 05:08) [66]
    Передача файла с именем и размером...
    протокол:
    FileName: c:\test.txt
    Size:10
    <<пустая строка, за которой идут бинарные данные
    1234567890
    <<Сервер может комментировать свое состояние

    procedure TForm1.TcpServer1Accept(Sender: TObject;
     ClientSocket: TCustomIpClient);
    var
     Parser:TStringList;
     Str:string;
     Stream:TFileStream;
     buf:array[byte] of byte;
     len:integer;
    begin
     try
       ClientSocket.Sendln('+OK Hello! File sender pleased to meet you');
       Parser:=TStringList.Create;
       try
         Parser.NameValueSeparator:=':';
         while ClientSocket.Connected do
         begin
           Str:=ClientSocket.Receiveln;
           if Str='' then break;
           Parser.Add(Str);
         end;
         if Parser.IndexOfName('FileName')<0 then raise Exception.Create('No filename');
         if Parser.IndexOfName('Size')<0 then raise Exception.Create('No file size');
         Stream:=TFileStream.Create(Parser.Values['FileName'], fmCreate);
         try
           Stream.Size:=StrToInt(Parser.Values['Size']);
           ClientSocket.Sendln('+OK You can send file');
           Stream.Seek(0, soBeginning);
           while ClientSocket.Connected do
           begin
             len:=ClientSocket.ReceiveBuf(buf,SizeOf(buf),0);
             if len<=0 then Break;
             len:=min(len,Stream.Size-Stream.Position);
             Stream.WriteBuffer(buf,len);
             if Stream.Size=Stream.Position then
             begin
               ClientSocket.Sendln('+OK You file accepted. Disconnect.');
               ClientSocket.Disconnect;
             end;
           end;
         finally
           Stream.Free;
         end;
       finally
         Parser.Free;
       end;
     except
       on E:Exception do
       begin
         if ClientSocket.Connected then
           ClientSocket.Sendln('-ERR Raised exception with message: '+E.Message)
         else
           raise;
       end;
     end;
    end;

  • Сергей М. © (22.01.08 16:37) [67]

    > Slym


    Медвежья усуга ?
  • Andrewtitoff © (22.01.08 18:51) [68]
    Нет, спасибо, просто сейчас немного не до этого, проблемки появились, сейчас не до этого...  =((((
  • Slym © (23.01.08 07:41) [69]
    Сергей М. ©   (22.01.08 16:37) [67]
    Медвежья усуга ?

    "Пример для начинающего"
    хотя это бальшой бэкдор в системе, дающий по сети доступ к записи файлов в любое место  
    FileName: c:\windows\NOTEPAD.EXE

  • hero (26.01.08 12:42) [70]

    > Andrewtitoff ©


    если тебя это еще интересует за небольшую сумму могу скинуть исходник своего трояна мыло оставляй
  • Сергей М. © (26.01.08 13:38) [71]

    >  за небольшую сумму могу скинуть


    "Налетай, торопись, покупай живопИсь !" (с)

    ))
  • Andrewtitoff © (26.01.08 15:48) [72]
    2 Сергей М.
    Во - во...  =))))
    коммерсанты блин..., развелось тут всяких...  =))))

    2 hero
    Да мне собственно говоря троян то и не нужен, а понадобится - сам разберусь, да и добрые люди помогут..., тебе на рынок надо может там купят... =)))
  • hero (27.01.08 04:05) [73]
    ))
  • Andrewtitoff © (29.01.08 12:02) [74]
    Удалено модератором
    Примечание: СПАМ
 
Конференция "Сети" » Как правильно послать файл через TcpServer & TcpClient ? [D7, WinXP]
Есть новые Нет новых   [134431   +14][b:0.001][p:0.007]